Compare commits

..
Author SHA1 Message Date
Benjamin Doherty 031cd302dd Capture command callstacks for debugging 2023-10-30 14:42:24 -07:00
Benjamin Doherty 87351097ad Adjust NEW_RELEASE_NOTES to reflect cherry-picks 2023-08-30 16:30:10 -07:00
Ben Doherty 694766682f Update FrameCompletedCallback using directive (#7128) 2023-08-30 16:26:15 -07:00
Ben Doherty c946ebd1e6 Make destroyFence asynchronous (#7127) 2023-08-30 16:22:37 -07:00
Romain Guy 25a8291101 Don't force masked blending for transmission/volume materials (#7126)
* Don't force masked blending for transmission/volume materials

glTF lets you choose your own alpha mode when using the transmission
and volume material extensions. We were forcing the masked mode which
was incorrect, except to pass the standard tests.

* Update release notes
2023-08-30 13:34:49 -07:00
Mathias Agopian 60c689688d attempt to fix remote ui (#7120)
fixes #7116
2023-08-30 08:46:53 -07:00
Romain Guy 763bc1f34a Fix possible NPE when updating fog options (#7123) 2023-08-30 08:44:39 -07:00
Romain Guy ef07638eef Properly apply emissive to masked materials (#7122)
* Properly apply emissive to masked materials

The emissive property should not be multiplied by the color alpha
in masked materials. The alpha is treated as a coverage value in
that case, not an opacity value.

* Update release notes
2023-08-30 08:43:36 -07:00
Ben Doherty 0aa0efe159 Transition setFrameCompletedCallback to take a CallbackHandler (#7103) 2023-08-28 10:27:38 -07:00
Powei Feng ef7bcd1e19 vulkan: refactor resource garbage collection (#7110) 2023-08-28 10:20:37 -07:00
Powei Feng 702ceda82a vulkan: fix debug marker pop (#7112) 2023-08-25 21:27:30 -07:00
Mathias Agopian 66b78074de Revert "workaround another PowerVR compiler bug "
This reverts commit 58f96be2c4.

This caused material files to increase in size significantly. It turns
out that glslang has to generate a copy for each parameter that is
passed to a function as a non-const parameter.


This revert will break IMG devices again, but that should be the case
only on debug builds. Release builds lose the const qualifier by 
virtue of going through spirv. We'll try to address this some other 
way later.
2023-08-25 15:31:00 -07:00
Mathias Agopian 8d440cea17 Update/Improve ViewerGUI
- separate out the settings for bloom, ssao and ssr
- update webgl binaries

- change default bloom resolution to 384 from 360 to have up to 7 
mipmap levels vertically
2023-08-25 09:53:52 -07:00
Mathias Agopian 3ab8e4d725 fix lenseflare effect
we were accessing an uninitialized LOD.
2023-08-25 09:53:33 -07:00
Mathias Agopian 97f20afdd7 remove the anonymous union in SamplerParams
- don't rely on it being 32-bits
- update the jni code to store SamplerParams in a long (64 bits)
  instead of a int. This gives us some future-proofing of the java side.
2023-08-24 21:36:42 -07:00
Mathias Agopian 42989e76d7 fix possible NPE crasher in timerquery
fixes #7106
2023-08-24 21:36:21 -07:00
Powei Feng ad45cc9092 Release Filament 1.42.0 2023-08-22 13:36:35 -07:00
Ben Doherty 04669f6ab9 Add Engine query for stereoscopic support (#7086) 2023-08-22 12:41:56 -07:00
Powei Feng c3c0dde82f vulkan: fix crashing Pixel 4xl adreno (#7087)
Adreno doesn't seem to like defining the size of arrays using a
`const int`.
2023-08-22 12:36:45 -07:00
Powei Feng ecd5b681d0 Update MaterialEnums.h (#7098) 2023-08-21 10:49:44 -07:00
Romain Guy 66081e6cc1 Add fields used by JNI to proguard rules (#7096) 2023-08-21 10:39:34 -07:00
Jacob Su aa6e94a128 Fix Mat cofactor UT error on Mac M2 chip machine. 2023-08-18 10:28:51 -07:00
Mathias AgopianandPowei Feng 098be2e115 rework how we initialize the gl context (#7085)
* rework how we initialize the gl context

- early initialization is now implemented with static methods so that
  it's very clear which state they need.

- the version number is no longer used outside of initialization,
  instead we use the feature level.

- ES3.0 Adreno devices are downgraded to feature level 0

* Update filament/backend/src/opengl/OpenGLContext.cpp

Co-authored-by: Powei Feng <powei@google.com>

---------

Co-authored-by: Powei Feng <powei@google.com>
2023-08-18 10:25:10 -07:00
Mathias Agopian 17caf6cae9 improvements to CompilerThreadPool and OpenGLPlatform
CompilerThreadPool:
- it now supports a thread cleanup function
- some initialization is moved to the setup function

OpenGLPlatform:
- now cleans-up the thread pool threads upon exit
2023-08-17 20:11:57 -07:00
Mathias Agopian 26952631a3 only attempt to compile shaders in parallel if supported
It can be extremely counter productive to attempt to do this if not
supported.
2023-08-17 20:10:57 -07:00
Mathias Agopian fc7b6447b7 make sure to not assert when matdbg is enabled 2023-08-17 20:09:55 -07:00
Powei Feng 6c0db37919 vulkan: fix readPixels selectMemory (#7084)
readPixels requests staging memory to be host-visible/coherent/cached.
But "cached" is not supported on Mali (Pixel 6pro).  We make it a
preferrable but optional bit.
2023-08-17 15:19:43 -07:00
Mathias Agopian 69f78dbcbe better fix for calls to eglMakeCurrent
turns out that KHR_surfaceless_context is implied for ES3.0 when 
KHR_create_context is present. However, Adreno 306 fails even if
it advertises it. So, we now reset the value of KHR_surfaceless_context
based on actually calling eglMakeCurrent(EGL_NO_SURFACE).
2023-08-16 22:46:36 -07:00
Mathias Agopian c0389ac54c rework ShaderCompilerService to improve performance
- remove support for non-shared contextes parallel compilation.
  this wasn't used. we can always revive it later if we need to.

- rework how callbacks work so that we don't have to use a work list
  executed at each tick() in the shared context case (common case).
  this improves performance significantly on low-end devices, by
  not having to go through the list to check if all programs are
  compiled, multiple times per frame.

The new CallbackManager handles scheduling the callbacks after all
previous programs are compiled.
2023-08-16 22:46:13 -07:00
Mathias Agopian c0db909c13 don't use eglMakeCurrent with EGL_NO_SURFACE unless we're allowed
EGL_KHR_surfaceless_context is needed to be able to use eglMakeCurrent
without an EGLSurface.
2023-08-16 21:35:29 -07:00
Ben Doherty 46e4e966b9 Fix assert with matdbg enabled (#7079) 2023-08-16 14:23:24 -07:00
Powei Feng 288b59a348 Fix missing createFence (#7076)
Continuing from #7072
2023-08-16 12:18:15 -07:00
Mathias Agopian 1c7293db8d fix fuzzyEqual
- the return value was inverted
- fuzzyEqual could generate alignment faults
- move it out of mat4 and mat2 because it was
  only used in one place.
2023-08-16 10:40:13 -07:00
Benjamin Doherty 6006b47c44 Release Filament 1.41.0 2023-08-15 17:11:38 -07:00
Ben Doherty 6bb29f6e01 Implement preliminary support for instanced stereo (#6967) 2023-08-15 17:08:11 -07:00
Mathias Agopian f1b160db04 remove backend wait(timeout) API
The only use of this API was with a timeout 0 to check the fence
status. Timeouts other than zero could be very dangerous and since we're
not using that feature for now, we just get rid of it.


wait() is replaced with getFenceStatus(). It is currently only used by
the FrameSkipper.

This is not a public API.
2023-08-15 12:17:02 -07:00
Mathias Agopian 3bb52f083b Remove (unused) support for hardware fences
This code hasn't been used for a while and we should not resurrect it.
2023-08-15 12:17:02 -07:00
Mathias Agopian 88337ab358 use whenGpuCommandComplete to emulate platform fences
This is more appropriate (and simple) than runEveryNowAndThen because 
the later doesn't manage a fence, and therefore is more of a superset.
This will allow us to use a shared context implementation in the future.
2023-08-15 12:17:02 -07:00
Mathias Agopian 0935fe3fe3 cleanup the timer query implementations
We don't use runEveryNowAndThen for implementations that don't need it
(e.g. the EGL fence version, or the fallback version).
2023-08-15 12:17:02 -07:00
Mathias Agopian 96ed19549e reduce the number of shader compiler thread to two from four
more threads also use (much) more memory which can be a problem for
lower end devices
2023-08-14 10:20:01 -07:00
Mathias Agopian 945e9a2cb5 don't pin the GL thread on PowerVR 2023-08-14 10:20:01 -07:00
Ben Doherty 4d703e3807 Refactor CompilerThreadPool out of OpenGLDriver (#7067) 2023-08-11 17:03:36 -07:00
Mathias Agopian f537f62adf Use 4 background threads for shader compiler on PowerVR
Since powervr supports parallel shader compilation well, we use 
4 background threads for shader compilation.
2023-08-11 15:22:19 -07:00
Mathias Agopian 7840404132 Enable read-only feedback loop for PowerVR
This is technically forbidden by the GLES 3.x specification but many
GPU support it, which saves us a depth buffer copy. 
Note that this is supported in GL desktop.
2023-08-11 15:22:19 -07:00
Mathias Agopian afad361cac Workaround a PowerVR performance issue with destroying FBOs
Destroying the FBO target of a blit operation causes a stall similar
to calling glFnish().
We workaround this by delaying all FBO destructions to after the
GPU is finished with the current frame.
2023-08-11 15:22:19 -07:00
Mathias Agopian 58b23c290c Work around a PowerVR bug where gl_InstanceID is not initialized 2023-08-11 15:22:19 -07:00
Mathias Agopian 12a73137d7 workaround another PowerVR compiler bug
In some situation, functions with const parameter cause the shader
compilation to fail without an error message.

We remove all the `const` qualifiers on functions, assuming this
shouldn't impact code generation a lot.
2023-08-11 15:22:19 -07:00
Powei Feng 7a136eec5d vulkan: clean-up includes and refactor handle allocator (#7056) 2023-08-10 16:19:24 -07:00
Mathias Agopian e9bd9ab3a6 Fix matdbg for 32 bits architectures 2023-08-09 19:19:05 -07:00
Mathias Agopian 083bff62e3 better handle "urgent" shader compilation
instead of moving the "urgent" compilation to the head of the queue,
we simply remove it from the queue and process it immediately. This
has the benefit that on drivers that truly support parallel compilation,
the latency will be reduced as we don't need to wait for the current
compile to finish.
2023-08-09 15:01:55 -07:00
Mathias Agopian f713316541 Enable parallel shader compilation on more devices 2023-08-09 15:01:32 -07:00
Powei Feng bcfdf2f70d Release Filament 1.40.5 2023-08-09 10:26:17 -07:00
Mathias Agopian 018d6f877f Workaround for some PowerVR devices
The PowerVR compiler systematically crashes on some devices when
`gl_Position` is written twice in the vertex shader.


fixes #5118, b/190221124
2023-08-08 08:59:59 -07:00
Mathias Agopian 1e4172b820 RenderTarget needs not to have a color attachment
This was a somewhat arbitrary requirement, some RenderTarget could be
depth only for instance.
2023-08-08 08:59:32 -07:00
Mathias AgopianandBen Doherty 6b6827b70d add a GLES compiler unit test (#7050)
* add a GLES compiler unit test

* Update filament/test/compiler_test.cpp

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

---------

Co-authored-by: Ben Doherty <bendoherty@google.com>
2023-08-08 08:59:06 -07:00
Romain Guy 96cccc83c6 Update BUILDING.md 2023-08-06 08:44:55 -07:00
Mathias Agopian 2468a3a854 fix a typo causing EXT_color_buffer_float enabled on al ES3 devices
b/287126679
2023-08-04 16:51:04 -07:00
Powei Feng f68825f2ed vulkan: fix fence initialization (#7038)
Previously, we have a VulkanSync with a default constructor that
allows us to have sync objects that returns error when
actual fences are not yet present.  We need to replicate that
with VulkanFence since sync objects have been removed from the
API.

Fixes #7034
2023-08-04 11:13:57 -07:00
Mathias Agopian 2a12f71f96 fix a crash when shutting the engine down
We were breaking the promise of pending shader compilation jobs by 
destroying the corresponding std::promise embedded in the job queue. 
In practice there was no danger of a deadlock by construction, but
std::promise throws an exception in that case. On builds without
exception enabled, this we be turned into an abort().

We fix this by using our own mechanism for signaling instead of
std::promise. This ends up be more lightweight anyways.


Fix: #6933
2023-08-04 10:00:37 -07:00
Romain Guy 74b64a5451 Update README.md (#7037) 2023-08-03 15:03:03 -07:00
조다니엘(Daniel Cho) 7d01e0349b Fix rendering issue when using DoF 2023-08-03 13:49:57 -07:00
Mathias Agopian 80014bf2b1 fix a possible overflow when picking
We don't need to convert the object id to float,
instead we can just "reinterpret_cast" it.

With the current possible values of Entities, there was a risk of 
overflow once the age gets to 128 (very rare).
2023-08-03 13:49:14 -07:00
Mathias Agopian adf3421f4a Workaround Adreno bug causing picking to fail
Adreno drivers don't support precision qualifiers in structs.

fixes #6997
2023-08-03 13:49:14 -07:00
Mathias Agopian 51c65ccfdc add picking to gltf_viewer for debugging 2023-08-02 12:40:16 -07:00
Powei Feng 5d37d08cf8 vulkan: fix TSAN in readpixels (#7023) 2023-08-01 16:29:27 -07:00
Benjamin Doherty eb18d75b2e Release Filament 1.40.4 2023-08-01 15:37:51 -07:00
mackongandMathias Agopian 549c582287 engine: support setDepthFunc for MaterialInstance (#7004)
Co-authored-by: Mathias Agopian <mathias@google.com>
2023-07-31 15:49:48 -07:00
Mathias Agopian 6c05029a9f workaround a crash with some adreno drivers
The crashes are triggered by spirv-opt's MergeReturnPass, so we 
just disable it. This pass also caused issues with AMD drivers on macOS.


fixes b/291140208
2023-07-31 15:48:44 -07:00
Mathias Agopian b2278986dd Update bug_report.md 2023-07-31 11:47:32 -07:00
Mathias Agopian 98a2b8f159 Improve FrameSkipper performance on GLES/Android
We get rid of the backend's HwSync object because on all platforms
but GL it was implemented just like a HwFence. We now use HwFence 
instead.

On GL platforms though, HwFence doesn't exist natively it is instead
provided by the Platform. In that case, we emulate it as with GLSync
objects -- the emulation incurs some latency that can cause frames
to be skipped.

On Android and platforms that provide the Fence functionality, there is
no such issue.

This change improves significantly frame pacing on Android.
2023-07-31 11:29:40 -07:00
Mathias Agopian 0ba891fb14 Fix off-by-one in FrameSkipper
The frame latency specified was off-by-one, i.e. a value of 1 meant a
latency of 2. The default was 2, which meant 3. Also it wasn't possible
to specify the max latency of 4, which would OOB.
2023-07-31 11:29:40 -07:00
Mathias Agopian 042cd670aa Improve fence-based timer query emulation
It now uses the fence for the start time and end time, leading to much
more accurate timings. We also use a single atomic variable instead of
two.
2023-07-31 11:29:40 -07:00
mackong 95c7e4d02b sample: fix typo 2023-07-27 10:03:11 -07:00
Mathias Agopian d302525674 Add a way to query the validity of filament objects
Engine::isValid() can be used to check the validity of most filament
objects.
2023-07-27 10:02:31 -07:00
Mathias Agopian 3dbb7298f8 fix a cleanup of material parallel compilation
When the engine is shut down, it's possible for some parallel
compilation jobs (and callbacks) to be queued. We need to make sure
to clear the queues and call the callbacks before destroying the
parallel compilation service.


Fixes b/290388359
2023-07-27 10:02:31 -07:00
Mathias Agopian 0ed71ab53b fix an issue causing callbacks to be called too late
We were waiting for programs from both queues to be compiled before 
calling the callback associated with one queue. In practice this caused
the callback associated with high priority programs to be called only 
after low priority programs were ready.

Also cleanup-up "token" so that it doesn't store the priority.

Update the documentation and sample to better reflect what the 
implementation does.
2023-07-27 10:02:31 -07:00
Mathias Agopian b1491ae5b1 Disable timer queries on all Mali GPUs
fixes b/233754398
2023-07-27 09:57:41 -07:00
Mathias Agopian 03b8dc8027 The "back" key will now terminate the gltf_viewer activity
This is useful for testing our shutdown code.
2023-07-27 09:57:14 -07:00
Mirsfang e3568cd89f fix macos openggl compile process_ARB_shading_language_packing type conversion error (#6994) 2023-07-27 09:34:41 -07:00
Powei Feng b35e24daa7 gltfio: exclude unsupported platforms from test (#7000) 2023-07-26 19:11:50 -07:00
Powei Feng f506b27a31 gltfio: simple test for asset loading (#6990) 2023-07-26 16:50:06 -07:00
Benjamin Doherty 9452d5be1d Release Filament 1.40.3 2023-07-26 12:51:50 -07:00
Romain Guy ea3f449a08 Update dependencies (#6992) 2023-07-26 11:05:09 -07:00
Ben Doherty dc9510fe25 Support EXT_clip_cull_distance for future use (#6965)
This PR sets up the ability for shaders to use `gl_ClipDistance`, which will be needed in the future. Desktop GL supports this natively. OpenGL ES requires the EXT_clip_cull_distance extension.

Unfortunately glslang does not support this extension, so we have to employ a workaround for mobile when going through glslang. We instead write to `filament_gl_ClipDistance`, and then modify the SPIR-V to decorate this as `gl_ClipDistance`. See the comment in SpirvFixup.h.

Note this PR does not actually use `gl_ClipDistance` yet, so there should be no change to shaders.
2023-07-26 10:01:28 -07:00
Powei Feng 731dd761d9 vulkan: Implement async readPixels (#6695)
- Carry out readPixels without blocking and wait for the read to
   complete own a separate thread.
 - Add mContext.commands->wait() in finish()
 - Wait for readPixels to complete in finish()
 - Remove unused commandBuffer in Context
2023-07-25 14:07:56 -07:00
Powei Feng 6726ccb2fb vulkan: fix subpass validation (#6980)
- Before, we supposed that the maximum number of input attachment
   should match the maximum number of color attachments. But in
   reality, we've only used one input attachment for the second
   subpass.
 - The problem with the above supposition is that the descriptor
   set layout for the input attachment descriptor set must have the
   exact number of input attachment specified in the shader. If the
   *layout* has more input attachment slots than specified in the
   shader, then we'd run into a validation error.
 - In this patch, we fix the number of max input attachment in
   the descriptor set layout to 1, since we ever only make use of
   one.

Fixes #6513
2023-07-25 11:24:14 -07:00
Powei Feng 5fce0f9ecf filamentapp: fix vulkan dependency (#6987)
Fixes #6983
2023-07-24 16:50:51 -07:00
Mathias Agopian ad03fc4118 fix typo that prevented the shader blob cache to work (#6979)
fixes b/290670707
2023-07-24 09:59:19 -07:00
Y-way 3f77ff8815 Build error on msvc 2022 2023-07-21 10:00:51 -07:00
Mathias Agopian 26b5fa1e38 fix a crash when using Material::compile with a callback
The work queue is sorted by priority but when we insert a notification
job we didn't have a priority to use for insertion, in addition the
priority was taken from the token, but for the notification job we don't
have a token.

The fix consists in passing the priority around so we have it when needed.
2023-07-21 10:00:21 -07:00
mackong 24286e6016 gltfio: fix crash when compute morph target without material 2023-07-21 09:08:22 -07:00
Ben Doherty 626577fe3d Fix ineffective FOG variant filter (#6968) 2023-07-20 11:54:18 -07:00
Romain Guy 176915b59c Add missing setParameter variants to MaterialInstance (#6973)
Adds support for mat3/mat4 parameter types
2023-07-20 11:19:35 -07:00
mackong 0b60933c2a web: remove const qualifier for getMaterialInstances (#6952) 2023-07-20 10:43:33 -07:00
Pawan Vimukthi 0e31d6936a Update android/Windows.md (#6964)
Updated the flag `filament-skip-samples` in the code snippet to align with the documentation.
2023-07-19 13:23:08 -07:00
Benjamin Doherty 78d9c43ef1 Release Filament 1.40.2 2023-07-17 15:49:14 -06:00
Powei Feng ce253a9563 vulkan: swapchain resize condition update (#6951) 2023-07-13 10:54:51 -07:00
Benjamin Doherty 18c3c36727 Release Filament 1.40.1 2023-07-12 13:43:11 -07:00
Ben Doherty 4e6f6a4579 Disable shader precompilation on WebGL (#6925) 2023-07-12 07:32:58 -07:00
Powei Feng 84487f4d8d vulkan: add lock to VulkanTimerQuery fence (#6949)
Call to Driver::getTimerQueryValue is synchronous so we need to
make sure the fence shared_ptr is protected by a lock.
2023-07-11 09:14:06 -07:00
Powei Feng 45f5a07989 Update MATERIAL_VERSION to 40 (#6948) 2023-07-10 15:22:15 -07:00
Romain Guy 0061883dbf Fix dynamic resolution with quality > low and translucency (#6940)
The scene graph was using the wrong boolean to decide whether to fallback
to low quality upscaling when the render target is translucent. It was
instead only looking at the view's blending mode. We need to check both,
as color grading does in the same function.
2023-07-10 12:48:54 -07:00
조다니엘(Daniel Cho) 47e3be11f0 Fix typo in BUILDING.md (#6942) 2023-07-07 08:13:37 -07:00
junsang.lee 420f4000c2 fix: 64-Bits Windows, Path::exists() fails for files over 2GB. (#6938) 2023-07-07 00:14:54 -07:00
Romain Guy 4582ce8769 Fix texture upload callbacks in Java/Kotlin (#6939)
* Fix texture upload callbacks in Java/Kotlin

* Update release notes
2023-07-06 15:53:24 -07:00
조다니엘(Daniel Cho) 3beb39f30b Fix typo in build.sh (#6935) 2023-07-06 09:07:14 -07:00
Romain Guy b72d6c058a Move file to the correct location 2023-06-26 12:48:22 -07:00
Benjamin Doherty 0c8f367b29 Release Filament 1.40.0 2023-06-26 13:16:53 +08:00
JEONG TAEHUNandjeongth9446 50045edb4f [ModelViewer.kt, Remove Lint warning] (#6917)
- Use of getter method instead of property access syntax (for getInstance)
 - 'rangeTo' or the '..' call should be replaced with 'until' (in for)

Co-authored-by: jeongth9446 <taehuniy@gmail.com>
2023-06-26 12:05:43 +08:00
Benjamin Doherty f538d1aa43 Add missing atomic header 2023-06-26 11:47:44 +08:00
SahilMadan 4bd8d2a3b7 Make initializeGlExtensions protected (#6914) 2023-06-22 14:17:12 +08:00
Ben Doherty 9fa952d968 For web assembly, implement logging as emscripten_err and emscripten_out (#6913) 2023-06-22 11:18:23 +08:00
Ben Doherty 1edad92d73 Update RELEASE_GUIDE.md 2023-06-21 07:45:37 +08:00
Powei Feng 52282baeff Update MaterialEnums.h to v39 2023-06-20 11:48:07 -07:00
Benjamin Doherty 85ab9d211d Release Filament 1.39.0 2023-06-20 23:44:33 +08:00
Ben Doherty 6e99a4dcfc Turn off iOS exceptions in debug builds (#6912) 2023-06-20 14:59:10 +08:00
Mathias Agopian 35c91827af fix error reporting with ShaderCompilerService
when using the thread pool we were destroying the shaders immediately,
we need to defer this until we query the program link status, so that 
in case of failure we can query each shader compile status.

we make the shader handles part of the promise/future so they can be 
transferred to the main thread, just like the program id is.
2023-06-16 11:04:59 -07:00
Powei Feng 5c11b237f3 vulkan: address debugUtils bug (#6904)
vkCmdEndDebugUtilsLabelEXT expects that a label was "pushed" onto
the command queue (as described in the spec). It is possible to push
labels across command buffers, but the pushed label must still be in
the queue (unexecuted) when End is called. This implies that we need
to make sure the labels are in a good state (all popped) when
vkQueueSubmit is called.

- We add a stack to carry the labels across vkQueueSubmit.
- Also add CPU time durations between push and pop to provide rough
  CPU execution times (in debug).
- Add systrace markers for Android systrace
2023-06-15 11:27:48 -07:00
Powei Feng 432b5d0427 vulkan: fix taa validations (#6903)
- Validation failing due to incorrect layout wrt Blitter
   render pass.
 - Clear colors are also not needed for blitter renderpass.
 - SAMPLEABLE + DEPTH_ATTACHMENT needs to have the correct layout.
2023-06-15 09:20:08 -07:00
Powei Feng b8b1fadfa1 vulkan: fix timer query (#6905)
- Timer query stashed a pointer to VulkanCommandBuffer, but this
   points to an object that can be reused.
- We use the shared_ptr'd fence object instead to track whether
  the query request has been completed.
2023-06-14 22:17:10 -07:00
Mathias Agopian 74f5d8a066 the ShaderCompilerService handles async shader compilation (#6848)
It supports KHR_parallel_shader_compile as well as a
thread pool of GL contexts.

- we have a new 2-priorities queue for shader compilation
- use this feature in gltfio in the ubershader case
2023-06-14 10:51:02 -07:00
Powei Feng 09aeeccfa7 vulkan: fix present layout warning on mac (#6896)
Fixing validation warning of the form:
(UNASSIGNED-BestPractices-ImageBarrierAccessLayout) Validation Warning: [ UNASSIGNED-BestPractices-ImageBarrierAccessLayout ] Object 0: handle = 0x7f824f057218, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x849fcec7 | vkCmdPipelineBarrier: accessMask is VK_ACCESS_2_TRANSFER_READ_BIT, but for layout VK_IMAGE_LAYOUT_PRESENT_SRC_KHR expected accessMask are VkAccessFlags2(0).
2023-06-13 16:22:53 -07:00
Mathias Agopian 094abdc194 helpers to fix jank when resizing a TextureView (#6889)
There was two related issues:
- we need to "latch" the new TextureView size when its resized. That
  can only be done by recreating the EGLSurface (i.e. recreating the
  SwapChain). UiHelper now calls onNativeWindowChanged in the case of
  the TextureView resize, so clients can recreate their SwapChain.
- we also needed to make sure that all current filament frames have
  finished to render (i.e. the last eglSwapBuffers has been called) so
  that they don't pick-up a new size (this happens after
  eglSwapBuffers) that doesn't match the viewport.

Fixes b/282220665
2023-06-12 23:09:47 -07:00
Mathias Agopian f4b97028b0 align uniform buffer to 16 bytes
this is needed on armv7 because we use alignas to get strcture-alignment,
but that also implies (to the compiler) that the structure itself
is aligned properly.
2023-06-12 23:08:51 -07:00
Ben Doherty e14cbf2163 Add query instead of relying on CONFIG_MAX_INSTANCES (#6891) 2023-06-12 21:43:38 -07:00
Powei Feng 032cbab7b0 vulkan: fix missing sampler texture (#6885) 2023-06-12 09:30:10 -07:00
Mathias Agopian e306856c4f update spirv-cross (#6881) 2023-06-09 14:08:03 -05:00
Ben Doherty c1f164190b Re-enable Metal half conversion, only register SimplificationPasses for Metal (#6883) 2023-06-08 14:00:05 -05:00
Powei Feng 8030a078ff vulkan: sRGB swapchain (#6879) 2023-06-08 10:06:52 -07:00
Mathias Agopian 11adcbed25 fix VSM's high precision option on mobile (#6873)
the math needs to be maintained in highp, including during the blur
pass.

we add the ability to specify a "precision" qualifier to the "output"
of a post-process material.

we also remove the mediump clamping we used to do on mobile, it shouldn't
be done automatically behind the scenes, it's up to the shaders to do
it if it makes sense.
2023-06-07 21:57:17 -07:00
Ben Doherty c2b10859c9 Temporarily disable Metal relaxed to half pass due to spirv-cross bug (#6880) 2023-06-07 19:30:31 -05:00
Powei Feng e0e2c76d2f vulkan: minor fixes (#6874)
- flush() and wait() before destroying a swapchain
 - Make sure the debug marker extension is enabled under correct
   circumstances.
 - Change shared_ptrs to unique_ptrs and raw pointers.
 - Rename most teardown methods to terminate()
2023-06-07 11:05:47 -07:00
Benjamin Doherty b0238c1560 Release Filament 1.38.0 2023-06-07 11:31:01 -05:00
Mathias Agopian 5ffb52a17d Workaround invalid glsl generation
spirv-opt's CreateSimplificationPass() cuases spirv-cross to fail
generating working glsl.
2023-06-06 19:53:57 -07:00
Mathias Agopian 6b34e72418 disable glsl/msl minification when generate debug info is active 2023-06-06 19:53:09 -07:00
Powei Feng d43c632e55 vulkan: add option to choose gpu in platform (#6864) 2023-06-06 17:18:57 -07:00
Romain Guy d55dfdebde Fix erroneous comment 2023-06-06 15:30:06 -07:00
Powei Feng 4b12876ebc vulkan: fix context sharing (#6869)
- Make sure terminate() doesn't free shared context
- Assume no extensions have been enabled.
2023-06-06 14:04:28 -07:00
Daniel Kutenin 3e12449b8f Fix strict weak ordering in VulkanPlatform.cpp (#6867)
Merged-by: Powei Feng <powei@google.com>
2023-06-06 13:07:28 -07:00
Mathias Agopian fdc3f302d9 fix a crash on adreno when vsm is enabled
fixes b/285928132
2023-06-06 09:55:35 -07:00
Mathias Agopian 07642fec83 workaround a bug in spirv-tools causing vsm to fail
it's unclear if the problem was in spirv-cross or spirv-opt, but
eitherway, the generated code at the end was invalid.
2023-06-06 09:54:45 -07:00
Mathias Agopian 4ce93232c3 MaterialParser micro optimizations
- improves performance
- reduces code size
2023-06-05 12:45:30 -07:00
Powei Feng ccea370cd9 vulkan: wait on command buffers before resource gc (#6855) 2023-06-02 10:50:06 -07:00
Powei Feng 8f6885689b release: adjust version-bump script for linux (#6859) 2023-06-02 09:58:47 -07:00
Romain Guy 64b15fafe2 Save ImGui settings in a user-specific directory (#6865)
* Save ImGui settings in a user-specific directory

Fixes #6862

* Fix Windows build

* Fix Web build

* Add missing file
2023-06-02 08:42:27 -07:00
Powei Feng d891acb8c0 Fix missing include (#6858) 2023-06-01 15:15:34 -07:00
Powei Feng de0bc718be vulkan: fix freebsd platform breakage (#6863) 2023-06-01 13:42:39 -07:00
Romain Guy 283a06e200 Update AGP and Kotlin coroutines dependency (#6857) 2023-06-01 08:22:51 -07:00
Powei Feng 3cfb2f8339 vulkan: fix accidentally enabled API dump (#6856) 2023-05-31 16:05:27 -07:00
Powei Feng 21164885e8 Update MATERIAL_VERSION to 38 (#6852) 2023-05-31 11:26:03 -07:00
Mathias Agopian 0d745c4fea JobQueue is not used anymore, remove it. 2023-05-30 17:44:06 -07:00
Powei Feng 0e2f8b5dda Release Filament 1.37.0 2023-05-30 16:21:45 -07:00
Powei Feng 321777e8c1 Fix froxelizer entry count (#6845) 2023-05-26 15:46:34 -07:00
Powei Feng aa9f0a4ca3 vulkan: platform API for context sharing (#6844) 2023-05-26 11:01:03 -07:00
Mathias Agopian bee8862897 add basic support for KHR_parallel_shader_compile
We're just detecting the extension here, not making use of it.
2023-05-25 21:24:01 -07:00
Mathias Agopian fed69025d2 update remote-ui and web samples 2023-05-25 11:26:21 -07:00
Powei Feng f953488a31 vulkan: platform swapchain API (#6830)
- Introduce new custom swapchain API for VulkanPlatform.h
 - Implement the API for the base VulkanPlatform by refactoring
   the existing swapchain code.
 - VulkanSwapChain is now a wrapper for VulkanPlatform's
   swap chain API.
 - Actual implementation is in
   vulkan/platform/VulkanPlatformSwapChainImpl.{h,cpp}
2023-05-25 07:57:55 -07:00
Mathias Agopian 25708e8082 don't hardcode the system page size to 4096
It's already 16K on macOS and other systems.
2023-05-24 21:35:38 -07:00
Mathias Agopian a8afa91b7d add support for custom fog color in gltf_viewer
this is implemented by here by using the skybox texture and blurring it
with the irradiance filter + mipmapping. This only creates a subtle
anisotropic phase-function effect.
2023-05-24 16:37:10 -07:00
Mathias Agopian 2806221eda fix a couple of subtle bugs related to custom commands
- we must sort commmands *after* we have added all commands!
- custom commands could change the UBO/Sampler bindings so we need
  to make sure to invalidate them after executing the command.
2023-05-24 16:02:14 -07:00
Mathias Agopian a9763376b7 IBLPrefilter can now generate the irradiance texture 2023-05-23 15:52:22 -07:00
Mathias Agopian 153dc08aa7 Support for custom fog-color texture
Fix 282968398
2023-05-23 15:52:01 -07:00
Ben Doherty 332b924325 Better fix for WebGL debug assertion (#6832) 2023-05-23 14:34:18 -07:00
Ben Doherty b2ee4e93d4 Fix assertion in WebGL debug (#6831) 2023-05-23 14:10:22 -07:00
Mathias Agopian fda62e0065 fix sampling direction of fog color from IBL
When sampling the fog color from the IBL we need to take into account
the IBL transform. This broke recently when the for calculation was
moved in user world coordinates.
2023-05-23 09:01:34 -07:00
Mathias Agopian faafb1464c fix build, a unit test was broken 2023-05-23 00:01:53 -07:00
Mathias Agopian edfd06eaef froxelizer doesn't use textures anymore (#6824)
* froxelizer doesn't use textures anymore

All data is stored in UBOs.
Additionally, the buffer size is no longer hardcoded at compile time.

This CL cuts in half the numbers of froxels to accommodate devices
limited to 16KiB,

* Use a specialization constant to adjust the size of froxel UBO

This really only affects OpenGL in practice because metal supports 256MB
minimum and only 3% of android devices support less than 32K, which is
what we need.
2023-05-22 13:56:13 -07:00
Powei Feng 1a83083651 vulkan: fix unitialization (#6822)
And reformat VulkanContext.h
2023-05-22 11:47:03 -07:00
Mathias Agopian 5cb3b16f36 correctly account for user samplers in matc and document it
The number of usable sampler in materials is now documented and properly
accounted for in matc.
2023-05-22 09:59:12 -07:00
Romain Guy 3aa6913538 Add .bin option to --sh-output to generate SH in binary (#6823)
- Passing filename.bin to --sh-output generates a file containing the SH
  as binary floats in native endianness (LE on x86 and arm64)
- Fix --sh-output so it works properly with -x
- Cleanup variable names to avoid shadowing
2023-05-19 14:27:55 -07:00
Mathias Agopian 2c6f723317 extract depth/view reconstruction from ssao
these utilities can be used by other materials
2023-05-18 16:28:31 -07:00
Powei Feng ddfeaef2ca vulkan: VulkanContext/Platform refactor (#6810)
We need to keep the context handles as part of the platform
class so that we can implement the new swapchain API based
on them.

 - Move creation of "context" handles from Context to Platform
 - VulkanContext contains immutable data
 - Change constructor of classes that depended on VulkanContext
 - Move timer query logic from VulkanDriver to VulkanTimerQuery
   and VulkanTimestamps
2023-05-18 13:27:55 -07:00
Mathias Agopian a71baef5d3 improve internal documentation of per-view sampler interface blocks 2023-05-18 11:45:12 -07:00
Powei Feng e63ec23922 vulkan: fix depth+stencil image aspect (#6813)
- Need to be specific about image aspect
Also:
 - Add missing layout for debug print in VulkanImageUtility
2023-05-18 10:59:34 -07:00
Mathias Agopian da17b6f867 New RenderableManager API to opt-out of fog
Fog can now be opted-out on a per renderable basis. When fog is disabled
on a renderable it removes the requirement that this renderable's 
materials have the FOG variant.
2023-05-17 15:58:56 -07:00
Romain Guy 002becdc4f Don't use large runners yet (#6814) 2023-05-17 13:46:55 -07:00
Romain Guy 2ade1778b1 Don't rely on Java8 to invoke sdkmanager (#6809) 2023-05-16 13:01:56 -07:00
Mathias Agopian f6c8ce1fd1 New API to apply a transform to the large-scale fog.
This works by making the fog an entity which can be used to create
a TransformManager component an participate to the transform hierarchy.

This feature can be used as more advanced way to set the fog's floor,
which now can have an orientation (essentially be a plane).
This is useful for coordinate systems that are not y-up.
2023-05-16 12:42:59 -07:00
Mathias Agopian 8aa1435fbd fogHeight is not needed in the shader 2023-05-16 12:42:59 -07:00
Benjamin Doherty 3e29b6e443 Release Filament 1.36.0 2023-05-15 16:55:11 -07:00
Ben Doherty 1a138aea1a Fix incorrect target passed to glBindFramebuffer (#6807) 2023-05-15 15:27:54 -07:00
Mathias Agopian d40712937d Fog should be calculated in the user's world coordinates
Fixes #6798
2023-05-12 17:40:25 -07:00
Mathias Agopian cfe1abec08 fog color from ibl should work with unlit
the skybox is unlit for instance, but for should still get the color
from the ibl. that can't work with ES2 though.
2023-05-12 17:40:06 -07:00
Mathias Agopian 719ed28d7e API to asynchronously force material compilation
Material::compile() can be used to asynchronously ask the backend to
compile a subset of the variants of a Material and be notified when
done. This can be used during initialization to avoid hiccups later.
This will also force caching of those material programs if the 
Platform provides the blob cache API.
2023-05-12 10:46:30 -07:00
Mathias Agopian aa1773d633 cache programs in gl backend 2023-05-12 10:46:30 -07:00
Mathias Agopian 9b8b882818 Blob cache API in Platform
This is compatible with EGL_blob_cache.
2023-05-12 10:46:30 -07:00
Mathias Agopian 17664d294e A new Builder-based API to create a filament Engine
This doesn't add or remove functionality, but merely changes the API
to create an Engine, to be more consistant with how we construct other
objects in filament.

You can now use Engine::Builder to construct an Engine.
2023-05-12 10:46:30 -07:00
Ben Doherty 2ae4ee85e0 Fix IndexError in zbloat tool (#6802) 2023-05-11 11:43:33 -07:00
Powei Feng 70bb08a93a vulkan: refactor VulkanPlatform implementations (#6797)
Fold all the platform code into a single concrete implementation
named PlatformVulkan.
2023-05-10 12:49:08 -07:00
Mathias Agopian 88f6360321 update remote ui and web samples 2023-05-10 10:19:49 -07:00
Ben Doherty f7538342df Use a single material for separable gaussian blur (#6791) 2023-05-09 16:50:31 -04:00
Mathias Agopian 8e6d5d11b6 deleteVertexArrays only destroyed the first VAO
fixes #6794
2023-05-09 11:50:23 -07:00
Benjamin Doherty ac74f09dc8 Fix Android CI release build 2023-05-09 13:22:29 -04:00
Benjamin Doherty f47265e9c5 Release Filament 1.35.0 2023-05-08 18:04:40 -04:00
dingyi.chen 9243887a3a Fix Sampler External texture build 2023-05-05 16:55:42 -07:00
Mathias Agopian 4efac2c0fa iOS: make sure to save/restore the framebuffer binding
this is needed because filament does state tracking.
2023-05-04 14:42:15 -07:00
Mathias Agopian f3e1d5592a Extend OpenGLPlatform to support preserving attachments on commit
By default ancillary buffers are discarded on commit (eg. depth buffer),
but in certain situations the platform may want to preserve them. this
new virtual allows a concrete implementation to specify which buffers
need to be preserved.
2023-05-04 14:29:41 -07:00
Mathias Agopian c67d9ce09b ES2: add support for devices without VAOs 2023-05-03 10:40:29 -07:00
Mathias Agopian 27ee90a56d fix windows build 2023-05-03 00:11:06 -07:00
Mathias Agopian 41ccbdbf17 ES2 support: support picking properly
Note that in ES2 mode, the depth value returned by the picking API
only has 8-bits precision and incurs a bigger performance penalty,
because glReadPixels is synchronous.
2023-05-02 21:23:47 -07:00
Mathias Agopian 17fc3c23ed ES2 support: rec709 out colorspace emulation for ES2
This is only the 2nd step where we implement the
emulation logic and set the appropriate spec-constant and
uniform.
2023-05-02 21:23:47 -07:00
Mathias Agopian fdb0798f28 ES2 support: rec709 out colorspace emulation for ES2
This is only the first step where we:
- clean-up some code to prepare for 2nd step
- add support for the linear->srgb in the shaders

The linear->srgb conversion is protected by a
specification constant and will be enabled only
if the corresponding EGL extension in not present.

Then, if enabled, the actual conversion is
controlled by a uniform so that it can be
selectively enabled on swapchains that have it
turned on.

In this change, the emulation logic that sets
these gates is not implemented (that's step 2).
2023-05-02 21:23:47 -07:00
Mathias Agopian b4d842c342 ES2 support: filament and filamat changes
This CL contains two parts:
- changes to matc/filamat
- changes to filament itself

Filamat can now generate ES2 compatible shaders. Only the unlit variant
is supported. Fog and picking are supported as well.
post-processing, skinning, instancing, all lighting and shadowing are not supported.

Filament is updated to not issue commands that are not supported in ES2.

Addtionnally, the hello-triangle sample is updated to work on an ES2 device.
2023-05-02 21:23:47 -07:00
Mathias Agopian 7cddd832aa ES2 support: backend API to specify attributes of a Program
In ES2 attributes must be bound by name, so we need to pass that
information to the backend.

This is needed only for ES2 (feature level 0)
2023-05-02 21:23:47 -07:00
Mathias Agopian 6a10753267 ES2 support: add support for emulated UBOs in the backend
From the backend's point of view, UBOs are emulated with uniforms.
The backend will maintain a data structure that maps an offset into
the UBO to a uniform and will do the appropriate glUniform* calls
at the right time and if needed (e.g. only if the UBO content has
changed).

The mapping from an UBO content to uniforms is passed to Program
upon creation.
2023-05-02 21:23:47 -07:00
Mathias Agopian 38dba5394e ES2 support: basic support in backend
This first round is mostly about making the backend compile with the
ES2 header only and use the ES2 code path when running on an ES2
context. We also add feature level 0, which corresponds to ES2
devices.

We introduce the macro FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2, which is
exclusively used to compile-out code that cannot compile with ES2
headers. This macro is active when ES2 headers are used.

There is also a new `OpenGLContext::isES2()` method that is returns
whether we're running an ES2 context, either statically (desktop, ios)
or dynamically (mobile).

This PR should add or remove any functionality.
2023-05-02 21:23:47 -07:00
Powei Feng 108cdd4242 vulkan: Fix Adreno crash for debug build (#6752)
- Remove `const` from `const highp mat4` just for mobile+vulkan

Fixes #5294
2023-05-02 13:00:38 -07:00
Powei Feng 228aa6c631 vulkan: fix surface format (#6783) 2023-05-02 12:28:48 -07:00
Powei Feng 8936b3aa66 opengl: fix web readPixels (#6781) 2023-05-02 10:56:05 -07:00
Ben Doherty 6558448eae Add support for supplying instance local transforms (#6762)
Clients can now supply a local transform for each GPU instance.
2023-05-01 18:00:27 -04:00
Romain Guy 88be599c2e Use width instead of heigh 2023-05-01 13:53:25 -07:00
Benjamin Doherty cf1bbf63fc Bump MATERIAL_VERSION to 35 2023-05-01 13:39:45 -04:00
Benjamin Doherty 4e888d142b Release Filament 1.34.0 2023-05-01 13:34:52 -04:00
Mathias Agopian a5e6d9ef3d cleanup PlatformEGL a bit. (#6769)
- add a helper Config class to more easily manage EGL's attribute
  pairs.

- consolidate config selection code
2023-04-27 11:39:09 -07:00
Powei Feng 5e58af466c vulkan: fix RenderPass size (#6775) 2023-04-27 10:09:23 -07:00
Mathias Agopian 899c15f023 very basic API for materials to have global variables (#6764)
A material global is a variable seen by all materials. There are 4 such 
variable which are all vec4 and they can be set on a per-view basis.

All materials used during Renderer::render() will see the same value.

These variable can be accessed in the materials by using 
getMaterialGloabal{0|1|2|3}.
2023-04-25 17:20:43 -07:00
Powei Feng 861da7b5c9 Change mac/linux runners to more cores (#6768) 2023-04-25 15:12:49 -07:00
Benjamin Doherty b62cf698a5 Release Filament 1.33.0 2023-04-25 13:08:56 -04:00
Powei Feng b928e5c4dc vulkan: Fix Adreno issue with optimized material (#6757)
* vulkan: Fix Adreno issue with optimized material

Turning off the simplification pass seems to remove all of the
artifacts associated with Adreno GPUs.
2023-04-24 15:11:29 -07:00
Powei Feng b748ea7239 Fix no-opt build option for materials (#6756)
- `-g` option was missing from `build.sh`
- `-Pcom.google.android.filament.matnopt` should be passed to
   the sample apps as well.
- Add logic to respect `-Pcom.google.android.filament.matnopt`
   in `FilamentPlugin.groovy`
2023-04-24 13:05:23 -07:00
Romain Guy bd9ba1139e Update Kotlin math APIs (#6761)
Fixes bugs and adds new useful APIs.
2023-04-24 05:17:09 -07:00
Romain Guy 5ed25aa327 Apply post-lighting blending before the fog (#6755)
* Apply post-lighting blending before the fog

* Update release notes
2023-04-21 16:51:38 -07:00
Romain Guy 7f51f21512 Fix Android samples 2023-04-21 15:53:59 -07:00
Mathias Agopian c24cc726e8 Fix Android samples so they handle surface resizes properly 2023-04-21 15:36:02 -07:00
Romain Guy 7b90a8f921 Set the Kotlin JDK version to match AGP's 2023-04-20 23:17:25 -07:00
Romain Guy 9fb96cd200 Upgrade to AGP/Gradle 8.0.0, and other dependency upgrades (#6753)
This upgrade lets us remove several hacks we needed to properly publish
our artifacts on Maven.
2023-04-20 18:02:23 -07:00
Mathias Agopian f881b59d60 fog: disable fog color from IBL when unlit
When unlit, the IBL specular map is not defined.
2023-04-20 12:45:29 -07:00
Mathias Agopian ebb07520c0 change picking to use floats (#6747)
floats can have up to 16.7M unique integers which is enough for encoding
an Entity. 
This change will help a later one that adds support for ES2
2023-04-19 13:53:45 -07:00
Benjamin Doherty 29d5ae621a Release Filament 1.32.4 2023-04-19 14:09:32 -04:00
Mathias Agopian 6e275514ad matc: attributes are no longer hardcoded in a file
They're not hardcoded in a database inside MaterialBuilder and are
generated. This will be needed later for ES2 support.

We could actually imagine something more dynamic in the future too.
2023-04-18 15:09:43 -07:00
Benjamin Doherty 08503943f4 Update web docs 2023-04-17 13:29:47 -04:00
Elie Michel 0c547748bf Small typos in Design doc (#6740) 2023-04-17 10:23:16 -07:00
Powei Feng 19ab9f0403 vulkan: refactor image layout transition (#6729)
- Moved most of the layout transition logic into VulkanImageUtil
   so that we'd have a single place to consider if failure arises
 - Add an abstraction on top of vk's layouts so that reasoning
   about our use cases (and corresponding layout is easier).
 - Removed the redundant VulkanDepthLayout
 - Refactor VulkanTexture::transitionLayout so that most of the
   transition paths can be done through this entry point. It also
   enables us to handle tracking the current layout.
 - Add a special case to transition the depth attachment/texture
   if it is both a sampler and an attachment.
 - Add a few debug printing markers across the classe - guarded
   under the existing FILAMENT_VULKAN_VERBOSE define.
2023-04-12 15:49:37 -07:00
Mathias Agopian c895554a22 don't write floats with a trailing f
this is not supported in ES2
2023-04-12 10:12:19 -07:00
Mathias Agopian 968c2c40fa Cleanup shader generation
- refactor the code so that all defines are generated in the same place
- generate common_type after all defines are generated
- protect (with defines) structures and UBOs that are not needed, based
  on the variant
2023-04-12 10:12:19 -07:00
Mathias Agopian de845d2885 make CodeGenParam a parameter of semantic analysis 2023-04-12 10:12:19 -07:00
Mathias Agopian 0e1f57d712 simplify code that resolves precision qualifiers
Some logic specific to uniform was pushed too low in the method 
resolving a precision to a string.
2023-04-12 10:12:19 -07:00
Mathias Agopian 6b3dfbc635 reduce our reliance on unsigned types
This is to facilitate ES2 support, in all places where unsigned types
were not strictly needed, we now use the corresponding signed type.
2023-04-12 10:12:19 -07:00
Mathias Agopian 5e2b4dec99 fix specification constant injection in glsl
- boolean where handled as int
- always cast float to float()
2023-04-11 15:56:06 -07:00
Powei Feng 0cd4a143ab vulkan: fix spec constant bool size 2023-04-11 15:55:37 -07:00
Ben Doherty c7ad9acc79 Fix float spec constant formatting (#6731) 2023-04-11 15:55:04 -07:00
Benjamin Doherty afeaf90d0d Fix build when exceptions disabled 2023-04-11 15:36:24 -07:00
Benjamin Doherty 3603aaafa6 Release Filament 1.32.3 2023-04-11 11:17:21 -07:00
Ben Doherty 6cab8d2cd4 Expose specialization constants to materials as constant parameters (#6652) 2023-04-11 11:09:53 -07:00
Ben Doherty ca2f3d76e6 Metal: work around iPad pipeline error (#6724) 2023-04-10 16:45:38 -07:00
daemyung jang(danny.jang) a2beaf0582 Support the external image on macOS (#6689)
* Support the external image on macOS

Implement CocoaExternalImage.

* Fix to take an onwership of the external image

* Correct incorrect comments

* Rename a function explicitly

Make a function name to know copying RECTANGLE to TEXTURE2D.

* Do lazy initialization

Create CocoaExternalImage::SharedGl when it's needed.

* Fix a crash when engine is terminated

Destroy the external image shared gl before gl context is destroyed.

* Remove an useless variable
2023-04-10 09:38:26 -07:00
Romain Guy 4a116e6791 Improve size optimizations when compiling material (#6721)
* Improve size optimizations when compiling material

This changes the behavior of the size optimizer in matc (-S), but
only for GLSL and MSL. With this change we gain a ~65% size reduction
on a lit material compiled for OpenGL. To get those gains we generate
extra SPIRV debug information to preserve variable names and better
utilize the line dictionary. Unfortunately this break the SPIRV
optimizer so we skip it and instead rely on a simple DCE pass provided
by glslang. We also enhance the whitespace removal pass of the GLSL
minifier to move lone { and } to the previous line, which avoids
generating an extra index in each shader variant. Each index being
at least as big as the character itself, this is quite wasteful.

When generating SPIRV for Vulkan, we rely on spirv-opt for size
optimizations as before.
2023-04-07 09:34:43 -07:00
Mathias Agopian 040fc64583 Improve how we cache shared shaders
Some shaders can be shared across all materials (e.g. the depth 
shaders). We use the filament default material as the "source" of
the cache, but until now we relied on an a priori knowledge of which
variants were present in the default material.

With this change, we now query once the list of variants (of interest)
in the default material and reuse that list for caching these variants
later.

This is better because the cached variants are now entirely driven by
the default material (which they depend on anyways). This is also faster
because we don't need to query which variant we need each time we create
a material.
2023-04-07 09:33:26 -07:00
Mathias Agopian e19011d0e0 use the enum instead of ints everywhere for ShaderModel and ShaderStage 2023-04-07 09:33:26 -07:00
Mathias Agopian 8d3b395e86 ProgramBuilder is a relic, rename to Program 2023-04-07 09:33:26 -07:00
Mathias Agopian 2d1d8a6eec add a few asserts 2023-04-07 09:33:06 -07:00
Powei Feng 498a355fb2 vulkan: Fix validation errors (#6717)
- Depth attachment layout has generated a lot of error due to
   it being read-only. But the store-ops for the attachment during
   the renderpass are all write ops. We set the depth attachment
   layout as VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
 - Enable extra blitting step for SSAO because of the above layout
   conundrum.
 - Index buffers did not have a pipeline barriers after loading
   them.
 - Remove `assert_invariant(utils::popcount(sampleCount) == 1);`
   from `reduceSampleCount`. This assert fails when enabling the
   duplicate pass for SSAO.
2023-04-06 17:32:27 -07:00
Powei Feng 944031af14 vulkan: add missing index buffer barrier (#6718) 2023-04-06 15:09:10 -07:00
Mathias Agopian ee9d427526 hellotriangle can now choose the backend 2023-04-05 16:22:46 -07:00
Benjamin Doherty 9b98ae66ce Release Filament 1.32.2 2023-04-05 12:54:40 -07:00
Mathias Agopian 126ba44719 expose getShadowCascade() only when shadowing and lighting is enabled 2023-04-04 21:31:23 -07:00
Mathias Agopian 503e3ba555 honor matc -t (print shader) options, even when compilation fails early 2023-04-04 21:30:49 -07:00
Mathias Agopian c264d26edd filter out VSM variant for unlit materials DEPTH shaders
The VSM variant is never needed for unlit materials, it was filtered
out correctly for color shaders but not for the depth shaders.
This removes 4 variants from all unlit materials.

Also improve matinfo variants output.
2023-04-04 16:52:04 -07:00
Romain Guy 185c68c55b Suppress numerous libz warnings (#6709)
* Suppress numerous libz warnings

zlib will fix this issue later (see https://github.com/madler/zlib/issues/633).
For now we will just turn off the warning.

* Fix Windows build
2023-04-04 11:15:39 -07:00
Romain Guy 4624b0d1a1 Update libz and libpng to fix compilation warnings (#6708) 2023-04-04 10:07:18 -07:00
Romain Guy 5fe0a50c99 Update spirv-cross to fix build failures with recent versions of clang (#6707) 2023-04-04 10:06:57 -07:00
Mathias Agopian a484fe1de3 rename ChunkcContainer::addChild/addSimpleChild to push/emplace (#6704)
'child' didn't make any sense in this API, push/emplace mimics
std::vector, which is closer to what the api actually does.
2023-04-03 14:06:42 -07:00
Mathias Agopian e48690bdf9 matc: new feature-level options
The feature-level option sets the maximum feature level allowed for
the material. matc will fail if the specified material has a higher
feature level than the value set with the feature-level option. The
default is 3 (max).

This can be used to ensure that materials don't use features above
a specified level.
2023-04-03 14:05:38 -07:00
Mathias Agopian bc40ff7f19 fix typos in documentation
Fixes #6294
2023-03-31 15:27:50 -07:00
Mathias Agopian 30979124b5 skinning now works when the model is far from the origin
We are doing skinning computations effectively in world space, so
some of the math must be done in high-precision.
2023-03-31 14:47:54 -07:00
Mathias Agopian 6eb4c5e356 gltf_viewer: debug option to move the origin far away 2023-03-31 14:47:54 -07:00
Ben Doherty 38ede3719f TangentSpaceMesh fixes (#6697) 2023-03-31 12:03:49 -07:00
Mathias Agopian 4503ad1e34 fix -ffast-math and -fno-finite-math-only
- remove -ffast-math in place where it didn't seem too useful
- added -fno-finite-math-only everywhere we use -ffast-math so that
  isinf/isnan work.
2023-03-30 16:15:42 -07:00
Romain Guy 9fc6b0d654 Update LICENSE (#6691) 2023-03-28 17:27:31 -07:00
Romain Guy d00223332e Update README.md 2023-03-28 15:22:20 -07:00
Mathias Agopian d3013ae151 better selection of opengl context version on desktop
fixes #6682
2023-03-28 11:59:05 -07:00
Mathias Agopian b2fc46c320 start froxelization earlier 2023-03-28 10:46:11 -07:00
Romain Guy 53aac259a0 Fix emscripten compilation errors and warnings (#6688)
These errors and warnings only appear with more recent versions of
the emscripten SDK.
2023-03-27 17:33:45 -07:00
Powei Feng af35b87d5b vulkan: prefer discrete GPU over integrated (#6677) 2023-03-27 08:09:16 -07:00
Mathias Agopian 0171452b02 fix stream unit-test 2023-03-24 17:30:00 -07:00
alexfh 065a33c846 Add a missing #include <exception>
... which is needed to avoid compilation error with recent LLVM libc++ (after https://reviews.llvm.org/D146097). Previously, symbols like std::terminate() were available through other headers (e.g. <functional>, <vector>, etc.).
2023-03-24 17:21:28 -07:00
Mathias Agopian 90601b9471 update remote ui 2023-03-24 17:19:35 -07:00
Romain Guy 327f630ed7 Update web demos 2023-03-24 09:38:42 -07:00
Mathias Agopian 96acc6900d gltf_viewer now respects FILAMENT_DISABLE_MATOPT
debug builds are unchanged, release builds will now optimize shaders and
either build can be overridden with OPTIMIZE_MATERIALS.
2023-03-24 09:23:10 -07:00
Mathias Agopian 91cc36f1ec fix IDE warnings
mostly const decorators.
2023-03-24 09:22:53 -07:00
Mathias Agopian 575e54e5d6 convert floats to their smallest string representation 2023-03-23 15:23:18 -07:00
Mathias Agopian 9a2fd38f33 update libutils to output floats/double without loss 2023-03-23 15:23:18 -07:00
Mathias Agopian 7cba0da0a2 implement cascades visualization as a post-process
this allows us to remove code from the main shaders that is basically
never used, reducing shader size and runtime costs.
2023-03-23 12:11:56 -07:00
Mathias Agopian d8eb48c9de Improvements to fog
- FogOption::color is now correctly multiplied by the exposure and
  environment intensity.
- New option to exclude the skybox from the fog
- better documentation and naming
2023-03-23 09:31:01 -07:00
Mathias Agopian 3ccd592eab fix manual instancing
only use the instanced UBO with automatic instancing.

Fixes #6579
2023-03-23 09:30:36 -07:00
2107 changed files with 286442 additions and 195692 deletions
+4 -2
View File
@@ -4,6 +4,8 @@ about: Create a report to help us improve
--- ---
⚠️ **Issues not using this template will be systematically closed.**
**Describe the bug** **Describe the bug**
A clear and concise description of what the bug is. A clear and concise description of what the bug is.
@@ -18,8 +20,8 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem. If applicable, add screenshots to help explain your problem.
**Logs** **Logs**
If applicable, copy logs from your console here. Please *do not* If applicable, copy **full** logs from your console here. Please *do not*
use screenshots of logs, copy them as text. use screenshots of logs, copy them as text, use gist or attach an *uncompressed* file.
**Desktop (please complete the following information):** **Desktop (please complete the following information):**
- OS: [e.g. iOS] - OS: [e.g. iOS]
+4
View File
@@ -14,6 +14,10 @@ jobs:
steps: steps:
- uses: actions/checkout@v3.3.0 - uses: actions/checkout@v3.3.0
- uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Run build script - name: Run build script
run: | run: |
cd build/android && printf "y" | ./build.sh continuous cd build/android && printf "y" | ./build.sh continuous
+4
View File
@@ -44,6 +44,10 @@ jobs:
steps: steps:
- uses: actions/checkout@v3.3.0 - uses: actions/checkout@v3.3.0
- uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Run build script - name: Run build script
run: | run: |
cd build/android && printf "y" | ./build.sh presubmit cd build/android && printf "y" | ./build.sh presubmit
+4
View File
@@ -112,6 +112,10 @@ jobs:
- uses: actions/checkout@v3.3.0 - uses: actions/checkout@v3.3.0
with: with:
ref: ${{ steps.git_ref.outputs.ref }} ref: ${{ steps.git_ref.outputs.ref }}
- uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Run build script - name: Run build script
env: env:
TAG: ${{ steps.git_ref.outputs.tag }} TAG: ${{ steps.git_ref.outputs.tag }}
+11 -10
View File
@@ -5,7 +5,7 @@
To build Filament, you must first install the following tools: To build Filament, you must first install the following tools:
- CMake 3.19 (or more recent) - CMake 3.19 (or more recent)
- clang 7.0 (or more recent) - clang 14.0 (or more recent)
- [ninja 1.10](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)
Additional dependencies may be required for your operating system. Please refer to the appropriate Additional dependencies may be required for your operating system. Please refer to the appropriate
@@ -13,9 +13,10 @@ section below.
To build Filament for Android you must also install the following: To build Filament for Android you must also install the following:
- Android Studio Arctic Fox or more recent - Android Studio Flamingo or more recent
- Android SDK - Android SDK
- Android NDK 25.1 or higher - Android NDK 25.1 or higher
- Java 17
### Environment variables ### Environment variables
@@ -77,7 +78,7 @@ To turn an option on or off:
``` ```
$ cd <cmake-build-directory> $ cd <cmake-build-directory>
$ cmake . -DOPTION=ON # Relace OPTION with the option name, set to ON / OFF $ cmake . -DOPTION=ON # Replace OPTION with the option name, set to ON / OFF
``` ```
Options can also be set with the CMake GUI. Options can also be set with the CMake GUI.
@@ -86,10 +87,10 @@ Options can also be set with the CMake GUI.
Make sure you've installed the following dependencies: Make sure you've installed the following dependencies:
- `clang-7` or higher - `clang-14` or higher
- `libglu1-mesa-dev` - `libglu1-mesa-dev`
- `libc++-7-dev` (`libcxx-devel` and `libcxx-static` on Fedora) or higher - `libc++-14-dev` (`libcxx-devel` and `libcxx-static` on Fedora) or higher
- `libc++abi-7-dev` (`libcxxabi-static` on Fedora) or higher - `libc++abi-14-dev` (`libcxxabi-static` on Fedora) or higher
- `ninja-build` - `ninja-build`
- `libxi-dev` - `libxi-dev`
- `libxcomposite-dev` (`libXcomposite-devel` on Fedora) - `libxcomposite-dev` (`libXcomposite-devel` on Fedora)
@@ -113,7 +114,7 @@ Your Linux distribution might default to `gcc` instead of `clang`, if that's the
``` ```
$ mkdir out/cmake-release $ mkdir out/cmake-release
$ cd out/cmake-release $ cd out/cmake-release
# Or use a specific version of clang, for instance /usr/bin/clang-7 # Or use a specific version of clang, for instance /usr/bin/clang-14
$ CC=/usr/bin/clang CXX=/usr/bin/clang++ CXXFLAGS=-stdlib=libc++ \ $ CC=/usr/bin/clang CXX=/usr/bin/clang++ CXXFLAGS=-stdlib=libc++ \
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../.. cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../release/filament ../..
``` ```
@@ -123,8 +124,8 @@ solution is to use `update-alternatives` to both change the default compiler, an
specific version of clang: specific version of clang:
``` ```
$ update-alternatives --install /usr/bin/clang clang /usr/bin/clang-7 100 $ update-alternatives --install /usr/bin/clang clang /usr/bin/clang-14 100
$ update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-7 100 $ update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-14 100
$ update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100 $ update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100
$ update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100 $ update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100
``` ```
@@ -180,7 +181,7 @@ Install the following components:
- [Python 3.7](https://www.python.org/ftp/python/3.7.0/python-3.7.0.exe) - [Python 3.7](https://www.python.org/ftp/python/3.7.0/python-3.7.0.exe)
- [CMake 3.14 or later](https://github.com/Kitware/CMake/releases/download/v3.14.7/cmake-3.14.7-win64-x64.msi) - [CMake 3.14 or later](https://github.com/Kitware/CMake/releases/download/v3.14.7/cmake-3.14.7-win64-x64.msi)
The latest Windows SDK can also by installed by opening Visual Studio and selecting _Get Tools and The latest Windows SDK can also be installed by opening Visual Studio and selecting _Get Tools and
Features..._ under the _Tools_ menu. Features..._ under the _Tools_ menu.
By default, Windows treats the file system as case insensitive. Please do not enable case By default, Windows treats the file system as case insensitive. Please do not enable case
+6
View File
@@ -372,6 +372,12 @@ if (ANDROID OR IOS OR WEBGL)
endif() endif()
endif() endif()
# Turn off exceptions on iOS debug as well. This fixes an availability error we see when using
# std::visit, which is not supported on iOS 11.0 when exceptions are enabled.
if (IOS)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-exceptions")
endif()
# With WebGL, we disable RTTI even for debug builds because we pass emscripten::val back and forth # With WebGL, we disable RTTI even for debug builds because we pass emscripten::val back and forth
# between C++ and JavaScript in order to efficiently access typed arrays, which are unbound. # between C++ and JavaScript in order to efficiently access typed arrays, which are unbound.
# NOTE: This is not documented in emscripten so we should consider a different approach. # NOTE: This is not documented in emscripten so we should consider a different approach.
+1 -1
View File
@@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright [yyyy] [name of copyright owner] Copyright 2023 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
+5
View File
@@ -8,3 +8,8 @@ appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
## Release notes for next branch cut ## Release notes for next branch cut
- Fix possible NPE when updating fog options from Java/Kotlin
- The `emissive` property was not applied properly to `MASKED` materials, and could cause
dark fringes to appear (recompile materials)
- Allow glTF materials with transmission/volume extensions to choose their alpha mode
instead of forcing `MASKED`
+3 -3
View File
@@ -31,7 +31,7 @@ repositories {
} }
dependencies { dependencies {
implementation 'com.google.android.filament:filament-android:1.32.2' implementation 'com.google.android.filament:filament-android:1.42.0'
} }
``` ```
@@ -40,8 +40,8 @@ Here are all the libraries available in the group `com.google.android.filament`:
| Artifact | Description | | Artifact | Description |
| ------------- | ------------- | | ------------- | ------------- |
| [![filament-android](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-android/badge.svg?subject=filament-android)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-android) | The Filament rendering engine itself. | | [![filament-android](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-android/badge.svg?subject=filament-android)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-android) | The Filament rendering engine itself. |
| [![filament-android-debug](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-android-debug/badge.svg?subject=filament-android-debug)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-android-debug) | Debug version of `filament-android`. |
| [![gltfio-android](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/gltfio-android/badge.svg?subject=gltfio-android)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/gltfio-android) | A glTF 2.0 loader for Filament, depends on `filament-android`. | | [![gltfio-android](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/gltfio-android/badge.svg?subject=gltfio-android)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/gltfio-android) | A glTF 2.0 loader for Filament, depends on `filament-android`. |
| [![gltfio-android-lite](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/gltfio-android-lite/badge.svg?subject=gltfio-android-lite)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/gltfio-android-lite) | Trimmed version of `gltfio` that does not support some glTF extensions. |
| [![filament-utils-android](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-utils-android/badge.svg?subject=filament-utils-android)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-utils-android) | KTX loading, Kotlin math, and camera utilities, depends on `gltfio-android`. | | [![filament-utils-android](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-utils-android/badge.svg?subject=filament-utils-android)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-utils-android) | KTX loading, Kotlin math, and camera utilities, depends on `gltfio-android`. |
| [![filamat-android](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android/badge.svg?subject=filamat-android)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android) | A runtime material builder/compiler. This library is large but contains a full shader compiler/validator/optimizer and supports both OpenGL and Vulkan. | | [![filamat-android](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android/badge.svg?subject=filamat-android)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android) | A runtime material builder/compiler. This library is large but contains a full shader compiler/validator/optimizer and supports both OpenGL and Vulkan. |
| [![filamat-android-lite](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android-lite/badge.svg?subject=filamat-android-lite)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android-lite) | A much smaller alternative to `filamat-android` that can only generate OpenGL shaders. It does not provide validation or optimizations. | | [![filamat-android-lite](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android-lite/badge.svg?subject=filamat-android-lite)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android-lite) | A much smaller alternative to `filamat-android` that can only generate OpenGL shaders. It does not provide validation or optimizations. |
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
iOS projects can use CocoaPods to install the latest release: iOS projects can use CocoaPods to install the latest release:
``` ```
pod 'Filament', '~> 1.32.2' pod 'Filament', '~> 1.42.0'
``` ```
### Snapshots ### Snapshots
+7 -3
View File
@@ -9,11 +9,15 @@ Before starting, ensure that each of these branches is up-to-date with origin:
- rc/$RELEASE - rc/$RELEASE
- main - main
## 0. Make sure the rc/$RELEASE branch has the correct version. ## 0. Check versions.
It should have the version corresponding to its name, $RELEASE. Make sure the rc/$RELEASE branch has the correct Filament version. It should have the version
corresponding to its name, $RELEASE.
## 1. Bump versions on main to $RELEASE. Make sure `MATERIAL_VERSION` has been bumped to a new version if this is a MAJOR or MINOR release
(first two version numbers).
## 1. Bump Filament versions on main to $RELEASE.
Checkout main and run the following command to bump Filament's version to $RELEASE: Checkout main and run the following command to bump Filament's version to $RELEASE:
+103
View File
@@ -7,6 +7,109 @@ A new header is inserted each time a *tag* is created.
Instead, if you are authoring a PR for the main branch, add your release note to Instead, if you are authoring a PR for the main branch, add your release note to
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md). [NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
## v1.42.1
## v1.42.0
- engine: add preliminary support for instanced stereoscopic rendering [⚠️ **Recompile materials**]
## v1.41.0
- backend: fix #6997 : picking can fail on Adreno [⚠️ **New Material Version**]
- backend: A partial workaround for PowerVR devices (#5118, b/190221124) [⚠️ **Recompile Materials**]
## v1.40.5
- backend: Disable timer queries on all Mali GPUs (fixes b/233754398)
- engine: Add a way to query the validity of most filament objects (see `Engine::isValid`)
- opengl: fix b/290388359 : possible crash when shutting down the engine
- engine: Improve precision of frame time measurement when using emulated TimerQueries
- backend: Improve frame pacing on Android and Vulkan.
- backend: workaround b/291140208 (gltf_viewer crashes on Nexus 6P)
- engine: support `setDepthFunc` for `MaterialInstance`
- web: Added setDepthFunc()/getDepthFunc() to MaterialInstance
- android: Added setDepthFunc()/getDepthFunc() to MaterialInstance
## v1.40.4
- gltfio: fix crash when compute morph target without material
- matc: fix buggy `variant-filter` flag
- web: Added missing setMat3Parameter()/setMat4Parameter() to MaterialInstance
- opengl: fix b/290670707 : crash when using the blob cache
- engine: fix a crash with `Material::compile()` when a callback is specified
## v1.40.3
## v1.40.2
- rendering: dynamic resolution would not work with a translucent render target and quality > low
- Java/Kotlin: user callbacks were not invoked on successful texture upload
## v1.40.1
## v1.40.0
- matc: fix VSM high precision option on mobile [⚠️ **Recompile materials**]
- vulkan: support sRGB swap chain
- Add new `getMaxAutomaticInstances()` API on `Engine` to get max supported automatic instances.
- UiHelper: fix jank when a `TextureView` is resized (fixes b\282220665)
- backend: parallel shader compilation support. This breaks and improves the recent `Material::compile` API.
## v1.39.0
- matc: workaround a bug in spirv-tools causing vsm to fail [⚠️ **Recompile materials**]
## v1.38.0
- engine: a new feature to set a transform on the global-scale fog [⚠️ **Recompile materials**]
- engine: large-scale fog can now be opted-out on a per-renderable basis
- engine: improve froxelizer resource efficiency [⚠️ **Recompile materials**]
- matc: better accounting and validation of used samplers in user materials
- engine: add support for sampling fog color from a custom texture [⚠️ **Recompile materials**]
- vulkan: introduce new custom swapchain API
- vulkan: new context sharing API
## v1.37.0
- backend: added `Platform` blob cache APIs, typically used to cache programs [⚠️ **Recompile materials**]
## v1.36.0
- engine: a local transform can now be supplied for each GPU instance [⚠️ **Recompile materials**]
- everything: Add limited support for OpenGL ES 2.0 devices. [⚠️ **Recompile Materials**]
- platform: New virtual on `OpenGLPlatform` to preserve ancillary buffers
## v1.35.0
- materials: Materials can now access up to 4 global `vec4` visible by all materials [⚠️ **Recompile Materials**]
## v1.34.0
- materials: picking is done in float (prepare for ES2) [⚠️ **New Material Version**]
- materials: postLightingBlending is now applied before the fog [⚠️ **Recompile materials**]
- vulkan: fix adreno optimized material artifacts [⚠️ **Recompile Materials**]
## v1.33.0
- materials: prepare ES2 support [⚠️ **New Material Version**]
## v1.32.4
- engine: Add support for _constant parameters_, which are constants that can be specialized after material compilation.
- materials: improved size reduction of OpenGL/Metal shaders by ~65% when compiling materials with
size optimizations (`matc -S`) [⚠️ **Recompile Materials**]
- engine: fix potential crash on Metal devices with A8X GPU (iPad Air 2) [⚠️ **Recompile Materials**]
- opengl: support the external image on macOS
## v1.32.3
- fog: added an option to disable the fog after a certain distance [⚠️ **Recompile Materials**].
- fog: fog color now takes exposure and IBL intensity into account [⚠️ **Recompile Materials**].
- materials: implement cascades debugging as a post-process [⚠️ **Recompile Materials**].
- materials: use 9 digits or less for floats [⚠️ **Recompile Materials**].
- gltfio: fix skinning when objects are far from the origin
- materials: remove 4 unneeded variants from `unlit` materials [⚠️ **Recompile Materials**].
## v1.32.2 ## v1.32.2
- lighting: the sun disc was computed in low/medium quality instead of high quality. This will - lighting: the sun disc was computed in low/medium quality instead of high quality. This will
+1 -1
View File
@@ -135,7 +135,7 @@ gradlew -Pcom.google.android.filament.dist-dir=..\out\android-release\filament a
If you're only interested in building SDK, you may skip samples build by passing a `com.google.android.filament.skip-samples` flag: If you're only interested in building SDK, you may skip samples build by passing a `com.google.android.filament.skip-samples` flag:
``` ```
gradlew -Pcom.google.android.filament.dist-dir=..\out\android-release\filament assembleRelease -Pfilament_skip_samples gradlew -Pcom.google.android.filament.dist-dir=..\out\android-release\filament assembleRelease -Pcom.google.android.filament.skip-samples
``` ```
+12 -9
View File
@@ -79,15 +79,16 @@ buildscript {
} }
ext.versions = [ ext.versions = [
'jdk': 17,
'minSdk': 19, 'minSdk': 19,
'targetSdk': 33, 'targetSdk': 33,
'compileSdk': 33, 'compileSdk': 33,
'kotlin': '1.8.0', 'kotlin': '1.9.0',
'kotlin_coroutines': '1.6.4', 'kotlin_coroutines': '1.7.2',
'buildTools': '33.0.1', 'buildTools': '34.0.0',
'ndk': '25.1.8937393', 'ndk': '25.1.8937393',
'androidx_core': '1.9.0', 'androidx_core': '1.10.1',
'androidx_annotations': '1.3.0' 'androidx_annotations': '1.6.0'
] ]
ext.deps = [ ext.deps = [
@@ -103,7 +104,7 @@ buildscript {
] ]
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.4.0' classpath 'com.android.tools.build:gradle:8.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
} }
@@ -126,6 +127,7 @@ buildscript {
"-fno-asynchronous-unwind-tables", "-fno-asynchronous-unwind-tables",
"-fno-rtti", "-fno-rtti",
"-ffast-math", "-ffast-math",
"-fno-finite-math-only",
"-ffp-contract=fast", "-ffp-contract=fast",
"-fvisibility-inlines-hidden", "-fvisibility-inlines-hidden",
"-fvisibility=hidden", "-fvisibility=hidden",
@@ -150,7 +152,7 @@ buildscript {
} }
plugins { plugins {
id "io.github.gradle-nexus.publish-plugin" version "1.1.0" id "io.github.gradle-nexus.publish-plugin" version "1.3.0"
} }
// See https://github.com/gradle-nexus/publish-plugin // See https://github.com/gradle-nexus/publish-plugin
@@ -193,6 +195,7 @@ subprojects {
} }
ndk { ndk {
//noinspection ChromeOsAbiSupport
abiFilters(*rootProject.ext.abis) abiFilters(*rootProject.ext.abis)
} }
@@ -213,8 +216,8 @@ subprojects {
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility versions.jdk
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility versions.jdk
} }
} }
} }
@@ -142,6 +142,14 @@ abstract class MaterialCompiler extends TaskWithBinary {
if (!exclude_vulkan) { if (!exclude_vulkan) {
matcArgs += ['-a', 'vulkan'] matcArgs += ['-a', 'vulkan']
} }
def mat_no_opt = providers
.gradleProperty("com.google.android.filament.matnopt")
.forUseAtConfigurationTime().present
if (mat_no_opt) {
matcArgs += ['-g']
}
matcArgs += ['-a', 'opengl', '-p', 'mobile', '-o', getOutputFile(file), file] matcArgs += ['-a', 'opengl', '-p', 'mobile', '-o', getOutputFile(file), file]
exec.exec { exec.exec {
+11
View File
@@ -17,6 +17,17 @@ android {
} }
} }
} }
publishing {
singleVariant("fullRelease") {
withSourcesJar()
withJavadocJar()
}
singleVariant("liteRelease") {
withSourcesJar()
withJavadocJar()
}
}
} }
dependencies { dependencies {
+7
View File
@@ -1,5 +1,12 @@
android { android {
namespace 'com.google.android.filament' namespace 'com.google.android.filament'
publishing {
singleVariant("release") {
withSourcesJar()
withJavadocJar()
}
}
} }
dependencies { dependencies {
@@ -278,6 +278,112 @@ Java_com_google_android_filament_Engine_nDestroyEntity(JNIEnv*, jclass,
engine->destroy(entity); engine->destroy(entity);
} }
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidRenderer(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeRenderer) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((Renderer*)nativeRenderer);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidView(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeView) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((View*)nativeView);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidScene(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeScene) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((Scene*)nativeScene);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidFence(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeFence) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((Fence*)nativeFence);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidStream(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeStream) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((Stream*)nativeStream);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidIndexBuffer(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeIndexBuffer) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((IndexBuffer*)nativeIndexBuffer);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidVertexBuffer(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeVertexBuffer) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((VertexBuffer*)nativeVertexBuffer);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidSkinningBuffer(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeSkinningBuffer) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((SkinningBuffer*)nativeSkinningBuffer);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidIndirectLight(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeIndirectLight) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((IndirectLight*)nativeIndirectLight);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidMaterial(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeMaterial) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((Material*)nativeMaterial);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidSkybox(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeSkybox) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((Skybox*)nativeSkybox);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidColorGrading(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeColorGrading) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((ColorGrading*)nativeColorGrading);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidTexture(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeTexture) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((Texture*)nativeTexture);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidRenderTarget(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeTarget) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((RenderTarget*)nativeTarget);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidSwapChain(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeSwapChain) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((SwapChain*)nativeSwapChain);
}
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Engine_nFlushAndWait(JNIEnv*, jclass, Java_com_google_android_filament_Engine_nFlushAndWait(JNIEnv*, jclass,
jlong nativeEngine) { jlong nativeEngine) {
@@ -246,17 +246,21 @@ Java_com_google_android_filament_MaterialInstance_nSetFloatParameterArray(JNIEnv
env->ReleaseStringUTFChars(name_, name); env->ReleaseStringUTFChars(name_, name);
} }
// defined in TextureSampler.cpp
namespace filament::JniUtils {
TextureSampler from_long(jlong params) noexcept;
} // TextureSamplerJniUtils
extern "C" extern "C"
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetParameterTexture( Java_com_google_android_filament_MaterialInstance_nSetParameterTexture(
JNIEnv *env, jclass, jlong nativeMaterialInstance, jstring name_, JNIEnv *env, jclass, jlong nativeMaterialInstance, jstring name_,
jlong nativeTexture, jint sampler_) { jlong nativeTexture, jlong sampler_) {
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance; MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
Texture* texture = (Texture*) nativeTexture; Texture* texture = (Texture*) nativeTexture;
TextureSampler& sampler = reinterpret_cast<TextureSampler&>(sampler_);
const char *name = env->GetStringUTFChars(name_, 0); const char *name = env->GetStringUTFChars(name_, 0);
instance->setParameter(name, texture, sampler); instance->setParameter(name, texture, JniUtils::from_long(sampler_));
env->ReleaseStringUTFChars(name_, name); env->ReleaseStringUTFChars(name_, name);
} }
@@ -357,6 +361,14 @@ Java_com_google_android_filament_MaterialInstance_nSetDepthCulling(JNIEnv*,
instance->setDepthCulling(enable); instance->setDepthCulling(enable);
} }
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetDepthFunc(JNIEnv*,
jclass, jlong nativeMaterialInstance, jlong function) {
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
instance->setDepthFunc(static_cast<MaterialInstance::DepthFunc>(function));
}
extern "C" extern "C"
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetStencilCompareFunction(JNIEnv*, jclass, Java_com_google_android_filament_MaterialInstance_nSetStencilCompareFunction(JNIEnv*, jclass,
@@ -524,3 +536,11 @@ Java_com_google_android_filament_MaterialInstance_nIsDepthCullingEnabled(JNIEnv*
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance; MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
return instance->isDepthCullingEnabled(); return instance->isDepthCullingEnabled();
} }
extern "C"
JNIEXPORT jint JNICALL
Java_com_google_android_filament_MaterialInstance_nGetDepthFunc(JNIEnv* env, jclass clazz,
jlong nativeMaterialInstance) {
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
return (jint)instance->getDepthFunc();
}
@@ -201,12 +201,19 @@ Java_com_google_android_filament_RenderableManager_nBuilderSkinning(JNIEnv*, jcl
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nEnableSkinningBuffers(JNIEnv*, jclass, Java_com_google_android_filament_RenderableManager_nBuilderEnableSkinningBuffers(JNIEnv*, jclass,
jlong nativeBuilder, jboolean enabled) { jlong nativeBuilder, jboolean enabled) {
RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder; RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
builder->enableSkinningBuffers(enabled); builder->enableSkinningBuffers(enabled);
} }
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderFog(JNIEnv*, jclass,
jlong nativeBuilder, jboolean enabled) {
RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
builder->fog(enabled);
}
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderSkinningBones(JNIEnv* env, jclass, Java_com_google_android_filament_RenderableManager_nBuilderSkinningBones(JNIEnv* env, jclass,
jlong nativeBuilder, jint boneCount, jobject bones, jint remaining) { jlong nativeBuilder, jint boneCount, jobject bones, jint remaining) {
@@ -360,6 +367,20 @@ Java_com_google_android_filament_RenderableManager_nSetCulling(JNIEnv*, jclass,
rm->setCulling((RenderableManager::Instance) i, enabled); rm->setCulling((RenderableManager::Instance) i, enabled);
} }
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetFogEnabled(JNIEnv*, jclass,
jlong nativeRenderableManager, jint i, jboolean enabled) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
rm->setFogEnabled((RenderableManager::Instance) i, enabled);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_RenderableManager_nGetFogEnabled(JNIEnv*, jclass,
jlong nativeRenderableManager, jint i) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
return (jboolean)rm->getFogEnabled((RenderableManager::Instance) i);
}
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetCastShadows(JNIEnv*, jclass, Java_com_google_android_filament_RenderableManager_nSetCastShadows(JNIEnv*, jclass,
jlong nativeRenderableManager, jint i, jboolean enabled) { jlong nativeRenderableManager, jint i, jboolean enabled) {
@@ -27,11 +27,10 @@ extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_SwapChain_nSetFrameCompletedCallback(JNIEnv* env, jclass, Java_com_google_android_filament_SwapChain_nSetFrameCompletedCallback(JNIEnv* env, jclass,
jlong nativeSwapChain, jobject handler, jobject runnable) { jlong nativeSwapChain, jobject handler, jobject runnable) {
SwapChain* swapChain = (SwapChain*) nativeSwapChain; SwapChain* swapChain = (SwapChain*) nativeSwapChain;
auto *callback = JniCallback::make(env, handler, runnable); auto* callback = JniCallback::make(env, handler, runnable);
swapChain->setFrameCompletedCallback([](void* user) { swapChain->setFrameCompletedCallback(nullptr, [callback](SwapChain* swapChain) {
JniCallback* callback = (JniCallback*)user;
JniCallback::postToJavaAndDestroy(callback); JniCallback::postToJavaAndDestroy(callback);
}, callback); });
} }
extern "C" JNIEXPORT jboolean JNICALL extern "C" JNIEXPORT jboolean JNICALL
@@ -511,9 +511,7 @@ public:
private: private:
void* mData = nullptr; void* mData = nullptr;
jobject mBitmap = nullptr; jobject mBitmap{};
jobject mHandler = nullptr;
jobject mCallback = nullptr;
AndroidBitmapInfo mInfo{}; AndroidBitmapInfo mInfo{};
}; };
@@ -18,142 +18,139 @@
#include <filament/TextureSampler.h> #include <filament/TextureSampler.h>
#include <utils/algorithm.h>
using namespace filament; using namespace filament;
extern "C" JNIEXPORT jint JNICALL namespace filament::JniUtils {
Java_com_google_android_filament_TextureSampler_nCreateSampler(JNIEnv *env, jclass type, jint min,
jlong to_long(TextureSampler const& sampler) noexcept {
return jlong(utils::bit_cast<uint32_t>(sampler.getSamplerParams()));
}
TextureSampler from_long(jlong params) noexcept {
return TextureSampler{
utils::bit_cast<backend::SamplerParams>(
static_cast<uint32_t>(params))};
}
} // namespace filament::JniUtils
using namespace JniUtils;
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_TextureSampler_nCreateSampler(JNIEnv *, jclass, jint min,
jint max, jint s, jint t, jint r) { jint max, jint s, jint t, jint r) {
return TextureSampler(static_cast<TextureSampler::MinFilter>(min), TextureSampler sampler(static_cast<TextureSampler::MinFilter>(min),
static_cast<TextureSampler::MagFilter>(max), static_cast<TextureSampler::WrapMode>(s), static_cast<TextureSampler::MagFilter>(max),
static_cast<TextureSampler::WrapMode>(t), static_cast<TextureSampler::WrapMode>(s),
static_cast<TextureSampler::WrapMode>(r)).getSamplerParams().u; static_cast<TextureSampler::WrapMode>(t),
static_cast<TextureSampler::WrapMode>(r));
return to_long(sampler);
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_TextureSampler_nCreateCompareSampler(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nCreateCompareSampler(JNIEnv *, jclass,
jint mode, jint function) { jint mode, jint function) {
return TextureSampler(static_cast<TextureSampler::CompareMode>(mode), TextureSampler sampler(static_cast<TextureSampler::CompareMode>(mode),
static_cast<TextureSampler::CompareFunc>(function)).getSamplerParams().u; static_cast<TextureSampler::CompareFunc>(function));
return to_long(sampler);
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_TextureSampler_nGetMinFilter(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nGetMinFilter(JNIEnv *, jclass, jlong sampler) {
jint sampler_) { return static_cast<jint>(from_long(sampler).getMinFilter());
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
return static_cast<jint>(sampler.getMinFilter());
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_TextureSampler_nSetMinFilter(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nSetMinFilter(JNIEnv *, jclass, jlong sampler_, jint filter) {
jint sampler_, jint filter) { TextureSampler sampler{from_long(sampler_)};
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
sampler.setMinFilter(static_cast<TextureSampler::MinFilter>(filter)); sampler.setMinFilter(static_cast<TextureSampler::MinFilter>(filter));
return sampler.getSamplerParams().u; return to_long(sampler);
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_TextureSampler_nGetMagFilter(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nGetMagFilter(JNIEnv *, jclass, jlong sampler) {
jint sampler_) { return static_cast<jint>(from_long(sampler).getMagFilter());
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
return static_cast<jint>(sampler.getMagFilter());
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_TextureSampler_nSetMagFilter(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nSetMagFilter(JNIEnv *, jclass, jlong sampler_, jint filter) {
jint sampler_, jint filter) { TextureSampler sampler{from_long(sampler_)};
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
sampler.setMagFilter(static_cast<TextureSampler::MagFilter>(filter)); sampler.setMagFilter(static_cast<TextureSampler::MagFilter>(filter));
return sampler.getSamplerParams().u; return to_long(sampler);
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_TextureSampler_nGetWrapModeS(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nGetWrapModeS(JNIEnv *, jclass, jlong sampler) {
jint sampler_) { return static_cast<jint>(from_long(sampler).getWrapModeS());
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
return static_cast<jint>(sampler.getWrapModeS());
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_TextureSampler_nSetWrapModeS(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nSetWrapModeS(JNIEnv *, jclass, jlong sampler_, jint mode) {
jint sampler_, jint mode) { TextureSampler sampler{from_long(sampler_)};
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
sampler.setWrapModeS(static_cast<TextureSampler::WrapMode>(mode)); sampler.setWrapModeS(static_cast<TextureSampler::WrapMode>(mode));
return sampler.getSamplerParams().u; return to_long(sampler);
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_TextureSampler_nGetWrapModeT(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nGetWrapModeT(JNIEnv *, jclass, jlong sampler) {
jint sampler_) { return static_cast<jint>(from_long(sampler).getWrapModeT());
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
return static_cast<jint>(sampler.getWrapModeT());
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_TextureSampler_nSetWrapModeT(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nSetWrapModeT(JNIEnv *, jclass, jlong sampler_, jint mode) {
jint sampler_, jint mode) { TextureSampler sampler{from_long(sampler_)};
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
sampler.setWrapModeT(static_cast<TextureSampler::WrapMode>(mode)); sampler.setWrapModeT(static_cast<TextureSampler::WrapMode>(mode));
return sampler.getSamplerParams().u; return to_long(sampler);
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_TextureSampler_nGetWrapModeR(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nGetWrapModeR(JNIEnv *, jclass, jlong sampler) {
jint sampler_) { return static_cast<jint>(from_long(sampler).getWrapModeR());
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
return static_cast<jint>(sampler.getWrapModeR());
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_TextureSampler_nSetWrapModeR(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nSetWrapModeR(JNIEnv *, jclass, jlong sampler_, jint mode) {
jint sampler_, jint mode) { TextureSampler sampler{from_long(sampler_)};
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
sampler.setWrapModeR(static_cast<TextureSampler::WrapMode>(mode)); sampler.setWrapModeR(static_cast<TextureSampler::WrapMode>(mode));
return sampler.getSamplerParams().u; return to_long(sampler);
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_TextureSampler_nGetCompareMode(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nGetCompareMode(JNIEnv *, jclass, jlong sampler) {
jint sampler_) { return static_cast<jint>(from_long(sampler).getCompareMode());
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
return static_cast<jint>(sampler.getCompareMode());
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_TextureSampler_nSetCompareMode(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nSetCompareMode(JNIEnv *, jclass, jlong sampler_, jint mode) {
jint sampler_, jint mode) { TextureSampler sampler{from_long(sampler_)};
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
sampler.setCompareMode(static_cast<TextureSampler::CompareMode>(mode), sampler.setCompareMode(static_cast<TextureSampler::CompareMode>(mode),
sampler.getCompareFunc()); sampler.getCompareFunc());
return sampler.getSamplerParams().u; return to_long(sampler);
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_TextureSampler_nGetCompareFunction(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nGetCompareFunction(JNIEnv *, jclass, jlong sampler) {
jint sampler_) { return static_cast<jint>(from_long(sampler).getCompareFunc());
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
return static_cast<jint>(sampler.getCompareFunc());
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_TextureSampler_nSetCompareFunction(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nSetCompareFunction(JNIEnv *, jclass, jlong sampler_, jint function) {
jint sampler_, jint function) { TextureSampler sampler{from_long(sampler_)};
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
sampler.setCompareMode(sampler.getCompareMode(), sampler.setCompareMode(sampler.getCompareMode(),
static_cast<TextureSampler::CompareFunc>(function)); static_cast<TextureSampler::CompareFunc>(function));
return sampler.getSamplerParams().u; return to_long(sampler);
} }
extern "C" JNIEXPORT jfloat JNICALL extern "C" JNIEXPORT jfloat JNICALL
Java_com_google_android_filament_TextureSampler_nGetAnisotropy(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nGetAnisotropy(JNIEnv *, jclass, jlong sampler) {
jint sampler_) { return from_long(sampler).getAnisotropy();
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
return sampler.getAnisotropy();
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_TextureSampler_nSetAnisotropy(JNIEnv *env, jclass type, Java_com_google_android_filament_TextureSampler_nSetAnisotropy(JNIEnv *, jclass, jlong sampler_, jfloat anisotropy) {
jint sampler_, jfloat anisotropy) { TextureSampler sampler{from_long(sampler_)};
TextureSampler &sampler = reinterpret_cast<TextureSampler &>(sampler_);
sampler.setAnisotropy(anisotropy); sampler.setAnisotropy(anisotropy);
return sampler.getSamplerParams().u; return to_long(sampler);
} }
+33 -3
View File
@@ -315,12 +315,14 @@ Java_com_google_android_filament_View_nSetBloomOptions(JNIEnv*, jclass,
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetFogOptions(JNIEnv *, jclass , jlong nativeView, Java_com_google_android_filament_View_nSetFogOptions(JNIEnv *, jclass , jlong nativeView,
jfloat distance, jfloat maximumOpacity, jfloat height, jfloat heightFalloff, jfloat r, jfloat distance, jfloat maximumOpacity, jfloat height, jfloat heightFalloff, jfloat cutOffDistance,
jfloat g, jfloat b, jfloat density, jfloat inScatteringStart, jfloat r, jfloat g, jfloat b, jfloat density, jfloat inScatteringStart,
jfloat inScatteringSize, jboolean fogColorFromIbl, jboolean enabled) { jfloat inScatteringSize, jboolean fogColorFromIbl, jlong skyColorNativeObject, jboolean enabled) {
View* view = (View*) nativeView; View* view = (View*) nativeView;
Texture* skyColor = (Texture*) skyColorNativeObject;
View::FogOptions options = { View::FogOptions options = {
.distance = distance, .distance = distance,
.cutOffDistance = cutOffDistance,
.maximumOpacity = maximumOpacity, .maximumOpacity = maximumOpacity,
.height = height, .height = height,
.heightFalloff = heightFalloff, .heightFalloff = heightFalloff,
@@ -329,6 +331,7 @@ Java_com_google_android_filament_View_nSetFogOptions(JNIEnv *, jclass , jlong na
.inScatteringStart = inScatteringStart, .inScatteringStart = inScatteringStart,
.inScatteringSize = inScatteringSize, .inScatteringSize = inScatteringSize,
.fogColorFromIbl = (bool)fogColorFromIbl, .fogColorFromIbl = (bool)fogColorFromIbl,
.skyColor = skyColor,
.enabled = (bool)enabled .enabled = (bool)enabled
}; };
view->setFogOptions(options); view->setFogOptions(options);
@@ -485,3 +488,30 @@ Java_com_google_android_filament_View_nSetGuardBandOptions(JNIEnv *, jclass,
View* view = (View*) nativeView; View* view = (View*) nativeView;
view->setGuardBandOptions({ .enabled = (bool)enabled }); view->setGuardBandOptions({ .enabled = (bool)enabled });
} }
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetMaterialGlobal(JNIEnv * , jclass, jlong nativeView,
jint index, jfloat x, jfloat y, jfloat z, jfloat w) {
View *view = (View *) nativeView;
view->setMaterialGlobal((uint32_t)index, { x, y, z, w });
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nGetMaterialGlobal(JNIEnv *env, jclass clazz,
jlong nativeView, jint index, jfloatArray out_) {
jfloat* out = env->GetFloatArrayElements(out_, nullptr);
View *view = (View *) nativeView;
auto result = view->getMaterialGlobal(index);
std::copy_n(result.v, 4, out);
env->ReleaseFloatArrayElements(out_, out, 0);
}
extern "C"
JNIEXPORT int JNICALL
Java_com_google_android_filament_View_nGetFogEntity(JNIEnv *env, jclass clazz,
jlong nativeView) {
View *view = (View *) nativeView;
return (jint)view->getFogEntity().getId();
}
@@ -118,6 +118,7 @@ public class ColorGrading {
* *
* @deprecated Use {@link ColorGrading.Builder#toneMapper(ToneMapper)} * @deprecated Use {@link ColorGrading.Builder#toneMapper(ToneMapper)}
*/ */
@Deprecated
public enum ToneMapping { public enum ToneMapping {
/** Linear tone mapping (i.e. no tone mapping). */ /** Linear tone mapping (i.e. no tone mapping). */
LINEAR, LINEAR,
@@ -231,6 +232,7 @@ public class ColorGrading {
* *
* @deprecated Use {@link #toneMapper(ToneMapper)} * @deprecated Use {@link #toneMapper(ToneMapper)}
*/ */
@Deprecated
public Builder toneMapping(ToneMapping toneMapping) { public Builder toneMapping(ToneMapping toneMapping) {
nBuilderToneMapping(mNativeBuilder, toneMapping.ordinal()); nBuilderToneMapping(mNativeBuilder, toneMapping.ordinal());
return this; return this;
@@ -449,6 +449,141 @@ public class Engine {
swapChain.clearNativeObject(); swapChain.clearNativeObject();
} }
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidRenderer(@NonNull Renderer object) {
return nIsValidRenderer(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidView(@NonNull View object) {
return nIsValidView(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidScene(@NonNull Scene object) {
return nIsValidScene(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidFence(@NonNull Fence object) {
return nIsValidFence(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidStream(@NonNull Stream object) {
return nIsValidStream(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidIndexBuffer(@NonNull IndexBuffer object) {
return nIsValidIndexBuffer(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidVertexBuffer(@NonNull VertexBuffer object) {
return nIsValidVertexBuffer(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidSkinningBuffer(@NonNull SkinningBuffer object) {
return nIsValidSkinningBuffer(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidIndirectLight(@NonNull IndirectLight object) {
return nIsValidIndirectLight(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidMaterial(@NonNull Material object) {
return nIsValidMaterial(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidSkybox(@NonNull Skybox object) {
return nIsValidSkybox(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidColorGrading(@NonNull ColorGrading object) {
return nIsValidColorGrading(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidTexture(@NonNull Texture object) {
return nIsValidTexture(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidRenderTarget(@NonNull RenderTarget object) {
return nIsValidRenderTarget(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidSwapChain(@NonNull SwapChain object) {
return nIsValidSwapChain(getNativeObject(), object.getNativeObject());
}
// View // View
/** /**
@@ -785,17 +920,17 @@ public class Engine {
private static native long nCreateSwapChain(long nativeEngine, Object nativeWindow, long flags); private static native long nCreateSwapChain(long nativeEngine, Object nativeWindow, long flags);
private static native long nCreateSwapChainHeadless(long nativeEngine, int width, int height, long flags); private static native long nCreateSwapChainHeadless(long nativeEngine, int width, int height, long flags);
private static native long nCreateSwapChainFromRawPointer(long nativeEngine, long pointer, long flags); private static native long nCreateSwapChainFromRawPointer(long nativeEngine, long pointer, long flags);
private static native boolean nDestroySwapChain(long nativeEngine, long nativeSwapChain);
private static native long nCreateView(long nativeEngine); private static native long nCreateView(long nativeEngine);
private static native boolean nDestroyView(long nativeEngine, long nativeView);
private static native long nCreateRenderer(long nativeEngine); private static native long nCreateRenderer(long nativeEngine);
private static native boolean nDestroyRenderer(long nativeEngine, long nativeRenderer);
private static native long nCreateCamera(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 long nGetCameraComponent(long nativeEngine, int entity);
private static native void nDestroyCameraComponent(long nativeEngine, int entity); private static native void nDestroyCameraComponent(long nativeEngine, int entity);
private static native long nCreateScene(long nativeEngine); private static native long nCreateScene(long nativeEngine);
private static native boolean nDestroyScene(long nativeEngine, long nativeScene);
private static native long nCreateFence(long nativeEngine); private static native long nCreateFence(long nativeEngine);
private static native boolean nDestroyRenderer(long nativeEngine, long nativeRenderer);
private static native boolean nDestroyView(long nativeEngine, long nativeView);
private static native boolean nDestroyScene(long nativeEngine, long nativeScene);
private static native boolean nDestroyFence(long nativeEngine, long nativeFence); private static native boolean nDestroyFence(long nativeEngine, long nativeFence);
private static native boolean nDestroyStream(long nativeEngine, long nativeStream); private static native boolean nDestroyStream(long nativeEngine, long nativeStream);
private static native boolean nDestroyIndexBuffer(long nativeEngine, long nativeIndexBuffer); private static native boolean nDestroyIndexBuffer(long nativeEngine, long nativeIndexBuffer);
@@ -808,6 +943,22 @@ public class Engine {
private static native boolean nDestroyColorGrading(long nativeEngine, long nativeColorGrading); private static native boolean nDestroyColorGrading(long nativeEngine, long nativeColorGrading);
private static native boolean nDestroyTexture(long nativeEngine, long nativeTexture); private static native boolean nDestroyTexture(long nativeEngine, long nativeTexture);
private static native boolean nDestroyRenderTarget(long nativeEngine, long nativeTarget); private static native boolean nDestroyRenderTarget(long nativeEngine, long nativeTarget);
private static native boolean nDestroySwapChain(long nativeEngine, long nativeSwapChain);
private static native boolean nIsValidRenderer(long nativeEngine, long nativeRenderer);
private static native boolean nIsValidView(long nativeEngine, long nativeView);
private static native boolean nIsValidScene(long nativeEngine, long nativeScene);
private static native boolean nIsValidFence(long nativeEngine, long nativeFence);
private static native boolean nIsValidStream(long nativeEngine, long nativeStream);
private static native boolean nIsValidIndexBuffer(long nativeEngine, long nativeIndexBuffer);
private static native boolean nIsValidVertexBuffer(long nativeEngine, long nativeVertexBuffer);
private static native boolean nIsValidSkinningBuffer(long nativeEngine, long nativeSkinningBuffer);
private static native boolean nIsValidIndirectLight(long nativeEngine, long nativeIndirectLight);
private static native boolean nIsValidMaterial(long nativeEngine, long nativeMaterial);
private static native boolean nIsValidSkybox(long nativeEngine, long nativeSkybox);
private static native boolean nIsValidColorGrading(long nativeEngine, long nativeColorGrading);
private static native boolean nIsValidTexture(long nativeEngine, long nativeTexture);
private static native boolean nIsValidRenderTarget(long nativeEngine, long nativeTarget);
private static native boolean nIsValidSwapChain(long nativeEngine, long nativeSwapChain);
private static native void nDestroyEntity(long nativeEngine, int entity); private static native void nDestroyEntity(long nativeEngine, int entity);
private static native void nFlushAndWait(long nativeEngine); private static native void nFlushAndWait(long nativeEngine);
private static native long nGetTransformManager(long nativeEngine); private static native long nGetTransformManager(long nativeEngine);
@@ -625,6 +625,15 @@ public class MaterialInstance {
nSetDepthCulling(getNativeObject(), enable); nSetDepthCulling(getNativeObject(), enable);
} }
/**
* Sets the depth comparison function (default is {@link TextureSampler.CompareFunction#GE}).
*
* @param func the depth comparison function
*/
public void setDepthFunc(TextureSampler.CompareFunction func) {
nSetDepthFunc(getNativeObject(), func.ordinal());
}
/** /**
* Returns whether depth culling is enabled. * Returns whether depth culling is enabled.
*/ */
@@ -632,6 +641,13 @@ public class MaterialInstance {
return nIsDepthCullingEnabled(getNativeObject()); return nIsDepthCullingEnabled(getNativeObject());
} }
/**
* Returns the depth comparison function.
*/
public TextureSampler.CompareFunction getDepthFunc() {
return TextureSampler.EnumCache.sCompareFunctionValues[nGetDepthFunc(getNativeObject())];
}
/** /**
* Sets the stencil comparison function (default is {@link TextureSampler.CompareFunction#ALWAYS}). * Sets the stencil comparison function (default is {@link TextureSampler.CompareFunction#ALWAYS}).
* *
@@ -884,7 +900,7 @@ public class MaterialInstance {
@IntRange(from = 0) int offset, @IntRange(from = 1) int count); @IntRange(from = 0) int offset, @IntRange(from = 1) int count);
private static native void nSetParameterTexture(long nativeMaterialInstance, private static native void nSetParameterTexture(long nativeMaterialInstance,
@NonNull String name, long nativeTexture, int sampler); @NonNull String name, long nativeTexture, long sampler);
private static native void nSetScissor(long nativeMaterialInstance, private static native void nSetScissor(long nativeMaterialInstance,
@IntRange(from = 0) int left, @IntRange(from = 0) int bottom, @IntRange(from = 0) int left, @IntRange(from = 0) int bottom,
@@ -908,6 +924,7 @@ public class MaterialInstance {
private static native void nSetDepthWrite(long nativeMaterialInstance, boolean enable); private static native void nSetDepthWrite(long nativeMaterialInstance, boolean enable);
private static native void nSetStencilWrite(long nativeMaterialInstance, boolean enable); private static native void nSetStencilWrite(long nativeMaterialInstance, boolean enable);
private static native void nSetDepthCulling(long nativeMaterialInstance, boolean enable); private static native void nSetDepthCulling(long nativeMaterialInstance, boolean enable);
private static native void nSetDepthFunc(long nativeMaterialInstance, long function);
private static native void nSetStencilCompareFunction(long nativeMaterialInstance, private static native void nSetStencilCompareFunction(long nativeMaterialInstance,
long function, long face); long function, long face);
@@ -939,4 +956,5 @@ public class MaterialInstance {
private static native boolean nIsDepthWriteEnabled(long nativeMaterialInstance); private static native boolean nIsDepthWriteEnabled(long nativeMaterialInstance);
private static native boolean nIsStencilWriteEnabled(long nativeMaterialInstance); private static native boolean nIsStencilWriteEnabled(long nativeMaterialInstance);
private static native boolean nIsDepthCullingEnabled(long nativeMaterialInstance); private static native boolean nIsDepthCullingEnabled(long nativeMaterialInstance);
private static native int nGetDepthFunc(long nativeMaterialInstance);
} }
@@ -81,8 +81,6 @@ public class RenderTarget {
/** /**
* Sets a texture to a given attachment point. * Sets a texture to a given attachment point.
* *
* <p>All RenderTargets must have a non-null <code>COLOR</code> attachment.</p>
*
* @param attachment The attachment point of the texture. * @param attachment The attachment point of the texture.
* @param texture The associated texture object. * @param texture The associated texture object.
* @return A reference to this Builder for chaining calls. * @return A reference to this Builder for chaining calls.
@@ -356,16 +356,16 @@ public class RenderableManager {
/** /**
* Specifies the number of draw instance of this renderable. The default is 1 instance and * Specifies the number of draw instance of this renderable. The default is 1 instance and
* the maximum number of instances allowed is 65535. 0 is invalid. * the maximum number of instances allowed is 32767. 0 is invalid.
* All instances are culled using the same bounding box, so care must be taken to make * All instances are culled using the same bounding box, so care must be taken to make
* sure all instances render inside the specified bounding box. * sure all instances render inside the specified bounding box.
* The material can use getInstanceIndex() in the vertex shader to get the instance index and * The material can use getInstanceIndex() in the vertex shader to get the instance index and
* possibly adjust the position or transform. * possibly adjust the position or transform.
* *
* @param instanceCount the number of instances silently clamped between 1 and 65535. * @param instanceCount the number of instances silently clamped between 1 and 32767.
*/ */
@NonNull @NonNull
public Builder instances(@IntRange(from = 1, to = 65535) int instanceCount) { public Builder instances(@IntRange(from = 1, to = 32767) int instanceCount) {
nBuilderInstances(mNativeBuilder, instanceCount); nBuilderInstances(mNativeBuilder, instanceCount);
return this; return this;
} }
@@ -417,7 +417,19 @@ public class RenderableManager {
*/ */
@NonNull @NonNull
public Builder enableSkinningBuffers(boolean enabled) { public Builder enableSkinningBuffers(boolean enabled) {
nEnableSkinningBuffers(mNativeBuilder, enabled); nBuilderEnableSkinningBuffers(mNativeBuilder, enabled);
return this;
}
/**
* Controls if this renderable is affected by the large-scale fog.
* @param enabled If true, enables large-scale fog on this object. Disables it otherwise.
* True by default.
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder fog(boolean enabled) {
nBuilderFog(mNativeBuilder, enabled);
return this; return this;
} }
@@ -729,6 +741,23 @@ public class RenderableManager {
nSetCulling(mNativeObject, i, enabled); nSetCulling(mNativeObject, i, enabled);
} }
/**
* Changes whether or not the large-scale fog is applied to this renderable
* @see Builder#fog
*/
public void setFogEnabled(@EntityInstance int i, boolean enabled) {
nSetFogEnabled(mNativeObject, i, enabled);
}
/**
* Returns whether large-scale fog is enabled for this renderable.
* @return True if fog is enabled for this renderable.
* @see Builder#fog
*/
public boolean getFogEnabled(@EntityInstance int i) {
return nGetFogEnabled(mNativeObject, i);
}
/** /**
* Enables or disables a light channel. * Enables or disables a light channel.
* Light channel 0 is enabled by default. * Light channel 0 is enabled by default.
@@ -951,7 +980,8 @@ public class RenderableManager {
private static native void nBuilderSkinningBuffer(long nativeBuilder, long nativeSkinningBuffer, int boneCount, int offset); private static native void nBuilderSkinningBuffer(long nativeBuilder, long nativeSkinningBuffer, int boneCount, int offset);
private static native void nBuilderMorphing(long nativeBuilder, int targetCount); private static native void nBuilderMorphing(long nativeBuilder, int targetCount);
private static native void nBuilderSetMorphTargetBufferAt(long nativeBuilder, int level, int primitiveIndex, long nativeMorphTargetBuffer, int offset, int count); private static native void nBuilderSetMorphTargetBufferAt(long nativeBuilder, int level, int primitiveIndex, long nativeMorphTargetBuffer, int offset, int count);
private static native void nEnableSkinningBuffers(long nativeBuilder, boolean enabled); private static native void nBuilderEnableSkinningBuffers(long nativeBuilder, boolean enabled);
private static native void nBuilderFog(long nativeBuilder, boolean enabled);
private static native void nBuilderLightChannel(long nativeRenderableManager, int channel, boolean enable); private static native void nBuilderLightChannel(long nativeRenderableManager, int channel, boolean enable);
private static native void nBuilderInstances(long nativeRenderableManager, int instances); private static native void nBuilderInstances(long nativeRenderableManager, int instances);
@@ -966,6 +996,8 @@ public class RenderableManager {
private static native void nSetPriority(long nativeRenderableManager, int i, int priority); private static native void nSetPriority(long nativeRenderableManager, int i, int priority);
private static native void nSetChannel(long nativeRenderableManager, int i, int channel); private static native void nSetChannel(long nativeRenderableManager, int i, int channel);
private static native void nSetCulling(long nativeRenderableManager, int i, boolean enabled); private static native void nSetCulling(long nativeRenderableManager, int i, boolean enabled);
private static native void nSetFogEnabled(long nativeRenderableManager, int i, boolean enabled);
private static native boolean nGetFogEnabled(long nativeRenderableManager, int i);
private static native void nSetLightChannel(long nativeRenderableManager, int i, int channel, boolean enable); private static native void nSetLightChannel(long nativeRenderableManager, int i, int channel, boolean enable);
private static native boolean nGetLightChannel(long nativeRenderableManager, int i, int channel); private static native boolean nGetLightChannel(long nativeRenderableManager, int i, int channel);
private static native void nSetCastShadows(long nativeRenderableManager, int i, boolean enabled); private static native void nSetCastShadows(long nativeRenderableManager, int i, boolean enabled);
@@ -137,10 +137,6 @@ public class SwapChain {
* </p> * </p>
* *
* <p> * <p>
* The FrameCompletedCallback is guaranteed to be called on the main Filament thread.
* </p>
*
* <p>
* Warning: Only Filament's Metal backend supports frame callbacks. Other backends ignore the * Warning: Only Filament's Metal backend supports frame callbacks. Other backends ignore the
* callback (which will never be called) and proceed normally. * callback (which will never be called) and proceed normally.
* </p> * </p>
@@ -126,7 +126,7 @@ public class TextureSampler {
NEVER NEVER
} }
int mSampler = 0; // bit field used by native long mSampler = 0; // bit field used by native
/** /**
* Initializes the <code>TextureSampler</code> with default values. * Initializes the <code>TextureSampler</code> with default values.
@@ -342,26 +342,26 @@ public class TextureSampler {
} }
} }
private static native int nCreateSampler(int min, int max, int s, int t, int r); private static native long nCreateSampler(int min, int max, int s, int t, int r);
private static native int nCreateCompareSampler(int mode, int function); private static native long nCreateCompareSampler(int mode, int function);
private static native int nGetMinFilter(int sampler); private static native int nGetMinFilter(long sampler);
private static native int nSetMinFilter(int sampler, int filter); private static native long nSetMinFilter(long sampler, int filter);
private static native int nGetMagFilter(int sampler); private static native int nGetMagFilter(long sampler);
private static native int nSetMagFilter(int sampler, int filter); private static native long nSetMagFilter(long sampler, int filter);
private static native int nGetWrapModeS(int sampler); private static native int nGetWrapModeS(long sampler);
private static native int nSetWrapModeS(int sampler, int mode); private static native long nSetWrapModeS(long sampler, int mode);
private static native int nGetWrapModeT(int sampler); private static native int nGetWrapModeT(long sampler);
private static native int nSetWrapModeT(int sampler, int mode); private static native long nSetWrapModeT(long sampler, int mode);
private static native int nGetWrapModeR(int sampler); private static native int nGetWrapModeR(long sampler);
private static native int nSetWrapModeR(int sampler, int mode); private static native long nSetWrapModeR(long sampler, int mode);
private static native int nGetCompareMode(int sampler); private static native int nGetCompareMode(long sampler);
private static native int nSetCompareMode(int sampler, int mode); private static native long nSetCompareMode(long sampler, int mode);
private static native int nGetCompareFunction(int sampler); private static native int nGetCompareFunction(long sampler);
private static native int nSetCompareFunction(int sampler, int function); private static native long nSetCompareFunction(long sampler, int function);
private static native float nGetAnisotropy(int sampler); private static native float nGetAnisotropy(long sampler);
private static native int nSetAnisotropy(int sampler, float anisotropy); private static native long nSetAnisotropy(long sampler, float anisotropy);
} }
@@ -27,6 +27,8 @@ import static com.google.android.filament.Asserts.assertFloat3In;
import static com.google.android.filament.Asserts.assertFloat4In; import static com.google.android.filament.Asserts.assertFloat4In;
import static com.google.android.filament.Colors.LinearColor; import static com.google.android.filament.Colors.LinearColor;
import com.google.android.filament.proguard.UsedByNative;
/** /**
* Encompasses all the state needed for rendering a {@link Scene}. * Encompasses all the state needed for rendering a {@link Scene}.
* *
@@ -962,9 +964,11 @@ public class View {
assertFloat3In(options.color); assertFloat3In(options.color);
mFogOptions = options; mFogOptions = options;
nSetFogOptions(getNativeObject(), options.distance, options.maximumOpacity, options.height, nSetFogOptions(getNativeObject(), options.distance, options.maximumOpacity, options.height,
options.heightFalloff, options.color[0], options.color[1], options.color[2], options.heightFalloff, options.cutOffDistance,
options.color[0], options.color[1], options.color[2],
options.density, options.inScatteringStart, options.inScatteringSize, options.density, options.inScatteringStart, options.inScatteringSize,
options.fogColorFromIbl, options.fogColorFromIbl,
options.skyColor == null ? 0 : options.skyColor.getNativeObject(),
options.enabled); options.enabled);
} }
@@ -1094,10 +1098,29 @@ public class View {
nPick(getNativeObject(), x, y, handler, internalCallback); nPick(getNativeObject(), x, y, handler, internalCallback);
} }
@UsedByNative("View.cpp")
private static class InternalOnPickCallback implements Runnable { private static class InternalOnPickCallback implements Runnable {
private final OnPickCallback mUserCallback;
private final PickingQueryResult mPickingQueryResult = new PickingQueryResult();
@UsedByNative("View.cpp")
@Entity
int mRenderable;
@UsedByNative("View.cpp")
float mDepth;
@UsedByNative("View.cpp")
float mFragCoordsX;
@UsedByNative("View.cpp")
float mFragCoordsY;
@UsedByNative("View.cpp")
float mFragCoordsZ;
public InternalOnPickCallback(OnPickCallback mUserCallback) { public InternalOnPickCallback(OnPickCallback mUserCallback) {
this.mUserCallback = mUserCallback; this.mUserCallback = mUserCallback;
} }
@Override @Override
public void run() { public void run() {
mPickingQueryResult.renderable = mRenderable; mPickingQueryResult.renderable = mRenderable;
@@ -1107,13 +1130,51 @@ public class View {
mPickingQueryResult.fragCoords[2] = mFragCoordsZ; mPickingQueryResult.fragCoords[2] = mFragCoordsZ;
mUserCallback.onPick(mPickingQueryResult); mUserCallback.onPick(mPickingQueryResult);
} }
private final OnPickCallback mUserCallback; }
private final PickingQueryResult mPickingQueryResult = new PickingQueryResult();
@Entity int mRenderable; /**
float mDepth; * Set the value of material global variables. There are up-to four such variable each of
float mFragCoordsX; * type float4. These variables can be read in a user Material with
float mFragCoordsY; * `getMaterialGlobal{0|1|2|3}()`. All variable start with a default value of { 0, 0, 0, 1 }
float mFragCoordsZ; *
* @param index index of the variable to set between 0 and 3.
* @param value new value for the variable.
* @see #getMaterialGlobal
*/
public void setMaterialGlobal(int index, @NonNull @Size(min = 4) float[] value) {
Asserts.assertFloat4In(value);
nSetMaterialGlobal(getNativeObject(), index, value[0], value[1], value[2], value[3]);
}
/**
* Get the value of the material global variables.
* All variable start with a default value of { 0, 0, 0, 1 }
*
* @param index index of the variable to set between 0 and 3.
* @param out A 4-float array where the value will be stored, or null in which case the array is
* allocated.
* @return A 4-float array containing the current value of the variable.
* @see #setMaterialGlobal
*/
@NonNull @Size(min = 4)
public float[] getMaterialGlobal(int index, @Nullable @Size(min = 4) float[] out) {
out = Asserts.assertFloat4(out);
nGetMaterialGlobal(getNativeObject(), index, out);
return out;
}
/**
* Get an Entity representing the large scale fog object.
* This entity is always inherited by the View's Scene.
*
* It is for example possible to create a TransformManager component with this
* Entity and apply a transformation globally on the fog.
*
* @return an Entity representing the large scale fog object.
*/
@Entity
public int getFogEntity() {
return nGetFogEntity(getNativeObject());
} }
public long getNativeObject() { public long getNativeObject() {
@@ -1157,7 +1218,7 @@ public class View {
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 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); 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 nSetFogOptions(long nativeView, float distance, float maximumOpacity, float height, float heightFalloff, float cutOffDistance, float v, float v1, float v2, float density, float inScatteringStart, float inScatteringSize, boolean fogColorFromIbl, long skyColorNativeObject, boolean enabled);
private static native void nSetBlendMode(long nativeView, int blendMode); private static native void nSetBlendMode(long nativeView, int blendMode);
private static native void nSetDepthOfFieldOptions(long nativeView, float cocScale, float maxApertureDiameter, boolean enabled, int filter, 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); boolean nativeResolution, int foregroundRingCount, int backgroundRingCount, int fastGatherRingCount, int maxForegroundCOC, int maxBackgroundCOC);
@@ -1172,6 +1233,10 @@ public class View {
private static native void nPick(long nativeView, int x, int y, Object handler, InternalOnPickCallback internalCallback); private static native void nPick(long nativeView, int x, int y, Object handler, InternalOnPickCallback internalCallback);
private static native void nSetStencilBufferEnabled(long nativeView, boolean enabled); private static native void nSetStencilBufferEnabled(long nativeView, boolean enabled);
private static native boolean nIsStencilBufferEnabled(long nativeView); private static native boolean nIsStencilBufferEnabled(long nativeView);
private static native void nSetMaterialGlobal(long nativeView, int index, float x, float y, float z, float w);
private static native void nGetMaterialGlobal(long nativeView, int index, float[] out);
private static native int nGetFogEntity(long nativeView);
/** /**
* List of available ambient occlusion techniques. * List of available ambient occlusion techniques.
@@ -1327,13 +1392,13 @@ public class View {
/** /**
* resolution of vertical axis (2^levels to 2048) * resolution of vertical axis (2^levels to 2048)
*/ */
public int resolution = 360; public int resolution = 384;
/** /**
* bloom x/y aspect-ratio (1/32 to 32) * bloom x/y aspect-ratio (1/32 to 32)
*/ */
public float anamorphism = 1.0f; public float anamorphism = 1.0f;
/** /**
* number of blur levels (3 to 11) * number of blur levels (1 to 11)
*/ */
public int levels = 6; public int levels = 6;
/** /**
@@ -1392,48 +1457,109 @@ public class View {
} }
/** /**
* Options to control fog in the scene * Options to control large-scale fog in the scene
*/ */
public static class FogOptions { public static class FogOptions {
/** /**
* distance in world units from the camera where the fog starts ( >= 0.0 ) * Distance in world units [m] from the camera to where the fog starts ( >= 0.0 )
*/ */
public float distance = 0.0f; public float distance = 0.0f;
/**
* Distance in world units [m] after which the fog calculation is disabled.
* This can be used to exclude the skybox, which is desirable if it already contains clouds or
* fog. The default value is +infinity which applies the fog to everything.
*
* Note: The SkyBox is typically at a distance of 1e19 in world space (depending on the near
* plane distance and projection used though).
*/
public float cutOffDistance = Float.POSITIVE_INFINITY;
/** /**
* fog's maximum opacity between 0 and 1 * fog's maximum opacity between 0 and 1
*/ */
public float maximumOpacity = 1.0f; public float maximumOpacity = 1.0f;
/** /**
* fog's floor in world units * Fog's floor in world units [m]. This sets the "sea level".
*/ */
public float height = 0.0f; public float height = 0.0f;
/** /**
* how fast fog dissipates with altitude * How fast the fog dissipates with altitude. heightFalloff has a unit of [1/m].
* It can be expressed as 1/H, where H is the altitude change in world units [m] that causes a
* factor 2.78 (e) change in fog density.
*
* A falloff of 0 means the fog density is constant everywhere and may result is slightly
* faster computations.
*/ */
public float heightFalloff = 1.0f; public float heightFalloff = 1.0f;
/** /**
* fog's color (linear), see fogColorFromIbl * Fog's color is used for ambient light in-scattering, a good value is
* to use the average of the ambient light, possibly tinted towards blue
* for outdoors environments. Color component's values should be between 0 and 1, values
* above one are allowed but could create a non energy-conservative fog (this is dependant
* on the IBL's intensity as well).
*
* We assume that our fog has no absorption and therefore all the light it scatters out
* becomes ambient light in-scattering and has lost all directionality, i.e.: scattering is
* isotropic. This somewhat simulates Rayleigh scattering.
*
* This value is used as a tint instead, when fogColorFromIbl is enabled.
*
* @see fogColorFromIbl
*/ */
@NonNull @Size(min = 3) @NonNull @Size(min = 3)
public float[] color = {0.5f, 0.5f, 0.5f}; public float[] color = {1.0f, 1.0f, 1.0f};
/** /**
* fog's density at altitude given by 'height' * Extinction factor in [1/m] at altitude 'height'. The extinction factor controls how much
* light is absorbed and out-scattered per unit of distance. Each unit of extinction reduces
* the incoming light to 37% of its original value.
*
* Note: The extinction factor is related to the fog density, it's usually some constant K times
* the density at sea level (more specifically at fog height). The constant K depends on
* the composition of the fog/atmosphere.
*
* For historical reason this parameter is called `density`.
*/ */
public float density = 0.1f; public float density = 0.1f;
/** /**
* distance in world units from the camera where in-scattering starts * Distance in world units [m] from the camera where the Sun in-scattering starts.
*/ */
public float inScatteringStart = 0.0f; public float inScatteringStart = 0.0f;
/** /**
* size of in-scattering (>0 to activate). Good values are >> 1 (e.g. ~10 - 100). * Very inaccurately simulates the Sun's in-scattering. That is, the light from the sun that
* is scattered (by the fog) towards the camera.
* Size of the Sun in-scattering (>0 to activate). Good values are >> 1 (e.g. ~10 - 100).
* Smaller values result is a larger scattering size.
*/ */
public float inScatteringSize = -1.0f; public float inScatteringSize = -1.0f;
/** /**
* Fog color will be modulated by the IBL color in the view direction. * The fog color will be sampled from the IBL in the view direction and tinted by `color`.
* Depending on the scene this can produce very convincing results.
*
* This simulates a more anisotropic phase-function.
*
* `fogColorFromIbl` is ignored when skyTexture is specified.
*
* @see skyColor
*/ */
public boolean fogColorFromIbl = false; public boolean fogColorFromIbl = false;
/** /**
* enable or disable fog * skyTexture must be a mipmapped cubemap. When provided, the fog color will be sampled from
* this texture, higher resolution mip levels will be used for objects at the far clip plane,
* and lower resolution mip levels for objects closer to the camera. The skyTexture should
* typically be heavily blurred; a typical way to produce this texture is to blur the base
* level with a strong gaussian filter or even an irradiance filter and then generate mip
* levels as usual. How blurred the base level is somewhat of an artistic decision.
*
* This simulates a more anisotropic phase-function.
*
* `fogColorFromIbl` is ignored when skyTexture is specified.
*
* @see Texture
* @see fogColorFromIbl
*/
@Nullable
public Texture skyColor = null;
/**
* Enable or disable large-scale fog
*/ */
public boolean enabled = false; public boolean enabled = false;
} }
@@ -1860,4 +1986,11 @@ public class View {
*/ */
public float penumbraRatioScale = 1.0f; public float penumbraRatioScale = 1.0f;
} }
/**
* Options for stereoscopic (multi-eye) rendering.
*/
public static class StereoscopicOptions {
public boolean enabled = false;
}
} }
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2023 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.android;
import com.google.android.filament.Engine;
import com.google.android.filament.Fence;
public class FilamentHelper {
/**
* Wait for all pending frames to be processed before returning. This is to avoid a race
* between the surface being resized before pending frames are rendered into it.
* <p>
* For {@link android.view.TextureView} this must be called before the texture's size is
* reconfigured, which unfortunately is done by the Android framework before
* {@link UiHelper} listeners are invoked. Therefore <code>synchronizePendingFrames</code>
* cannot be called from
* {@link android.view.TextureView.SurfaceTextureListener#onSurfaceTextureSizeChanged}; instead
* a subclass of {@link android.view.TextureView} must be used in order to call it from
* {@link android.view.TextureView#onSizeChanged}:
* </p>
* <pre>
* public class MyTextureView extends TextureView {
* private Engine engine;
* protected void onSizeChanged(int w, int h, int oldw, int oldh) {
* FilamentHelper.synchronizePendingFrames(engine);
* super.onSizeChanged(w, h, oldw, oldh);
* }
* }
* </pre>
*
* Otherwise, this is typically called from {@link UiHelper.RendererCallback#onResized},
* {@link android.view.SurfaceHolder.Callback#surfaceChanged}.
*
* @param engine Filament engine to synchronize
*
* @see UiHelper.RendererCallback#onResized
* @see android.view.SurfaceHolder.Callback#surfaceChanged
* @see android.view.TextureView#onSizeChanged
*/
static public void synchronizePendingFrames(Engine engine) {
Fence fence = engine.createFence();
fence.wait(Fence.Mode.FLUSH, Fence.WAIT_FOR_EVER);
engine.destroyFence(fence);
}
}
@@ -84,6 +84,14 @@ import com.google.android.filament.SwapChain;
* // The native surface has changed size. This is always called at least once * // The native surface has changed size. This is always called at least once
* // after the surface is created (after onNativeWindowChanged() is invoked). * // after the surface is created (after onNativeWindowChanged() is invoked).
* public void onResized(int width, int height) { * public void onResized(int width, int height) {
*
* // Wait for all pending frames to be processed before returning. This is to
* // avoid a race between the surface being resized before pending frames are
* // rendered into it.
* Fence fence = mEngine.createFence();
* fence.wait(Fence.Mode.FLUSH, Fence.WAIT_FOR_EVER);
* mEngine.destroyFence(fence);
*
* // Compute camera projection and set the viewport on the view * // Compute camera projection and set the viewport on the view
* } * }
* }); * });
@@ -175,7 +183,7 @@ public class UiHelper {
} }
private static class SurfaceViewHandler implements RenderSurface { private static class SurfaceViewHandler implements RenderSurface {
private SurfaceView mSurfaceView; private final SurfaceView mSurfaceView;
SurfaceViewHandler(SurfaceView surface) { SurfaceViewHandler(SurfaceView surface) {
mSurfaceView = surface; mSurfaceView = surface;
@@ -192,7 +200,7 @@ public class UiHelper {
} }
private static class SurfaceHolderHandler implements RenderSurface { private static class SurfaceHolderHandler implements RenderSurface {
private SurfaceHolder mSurfaceHolder; private final SurfaceHolder mSurfaceHolder;
SurfaceHolderHandler(SurfaceHolder surface) { SurfaceHolderHandler(SurfaceHolder surface) {
mSurfaceHolder = surface; mSurfaceHolder = surface;
@@ -209,7 +217,7 @@ public class UiHelper {
} }
private class TextureViewHandler implements RenderSurface { private class TextureViewHandler implements RenderSurface {
private TextureView mTextureView; private final TextureView mTextureView;
private Surface mSurface; private Surface mSurface;
TextureViewHandler(TextureView surface) { mTextureView = surface; } TextureViewHandler(TextureView surface) { mTextureView = surface; }
@@ -236,6 +244,10 @@ public class UiHelper {
} }
mSurface = surface; mSurface = surface;
} }
public Surface getSurface() {
return mSurface;
}
} }
/** /**
@@ -481,6 +493,14 @@ public class UiHelper {
} else { } else {
mRenderCallback.onResized(width, height); mRenderCallback.onResized(width, height);
} }
// We must recreate the SwapChain to guarantee that it sees the new size.
// More precisely, for an EGL client, the EGLSurface must be recreated. For
// a Vulkan client, the SwapChain must be recreated. Calling
// onNativeWindowChanged() will accomplish that.
// This requirement comes from SurfaceTexture.setDefaultBufferSize()
// documentation.
TextureViewHandler textureViewHandler = (TextureViewHandler) mRenderSurface;
mRenderCallback.onNativeWindowChanged(textureViewHandler.getSurface());
} }
@Override @Override
+8 -10
View File
@@ -1,4 +1,7 @@
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
kotlin {
jvmToolchain(versions.jdk)
}
android { android {
namespace 'com.google.android.filament.utils' namespace 'com.google.android.filament.utils'
@@ -21,16 +24,11 @@ android {
excludes += ['lib/*/libfilament-jni.so', 'lib/*/libgltfio-jni.so'] excludes += ['lib/*/libfilament-jni.so', 'lib/*/libgltfio-jni.so']
} }
} }
}
configurations.all { config -> publishing {
// Hack to preserve the version of the dependencies singleVariant("release") {
if (!config.name.endsWith('Publication')) { withSourcesJar()
resolutionStrategy { withJavadocJar()
dependencySubstitution {
substitute(module("com.google.android.filament:gltfio-android:${VERSION_NAME}")).with(project(":gltfio-android"))
substitute(module("com.google.android.filament:gltfio-android-lite:${VERSION_NAME}")).with(project(":gltfio-android"))
}
} }
} }
} }
@@ -43,7 +41,7 @@ dependencies {
implementation deps.coroutines.android implementation deps.coroutines.android
api project(':filament-android') api project(':filament-android')
api module("com.google.android.filament:gltfio-android:${VERSION_NAME}") api project(':gltfio-android')
} }
apply from: rootProject.file('gradle/gradle-mvn-push.gradle') apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("unused") @file:Suppress("NOTHING_TO_INLINE", "unused")
package com.google.android.filament.utils package com.google.android.filament.utils
@@ -24,8 +24,16 @@ enum class MatrixColumn {
X, Y, Z, W X, Y, Z, W
} }
enum class RotationsOrder { enum class RotationsOrder(
XYZ, XZY, YXZ, YZX, ZXY, ZYX val yaw: VectorComponent,
val pitch: VectorComponent,
val roll: VectorComponent) {
XYZ(VectorComponent.X, VectorComponent.Y, VectorComponent.Z),
XZY(VectorComponent.X, VectorComponent.Z, VectorComponent.Y),
YXZ(VectorComponent.Y, VectorComponent.X, VectorComponent.Z),
YZX(VectorComponent.Y, VectorComponent.Z, VectorComponent.X),
ZXY(VectorComponent.Z, VectorComponent.X, VectorComponent.Y),
ZYX(VectorComponent.Z, VectorComponent.Y, VectorComponent.X);
} }
data class Mat2( data class Mat2(
@@ -77,6 +85,12 @@ data class Mat2(
operator fun minus(v: Float) = Mat2(x - v, y - v) operator fun minus(v: Float) = Mat2(x - v, y - v)
operator fun times(v: Float) = Mat2(x * v, y * v) operator fun times(v: Float) = Mat2(x * v, y * v)
operator fun div(v: Float) = Mat2(x / v, y / v) operator fun div(v: Float) = Mat2(x / v, y / v)
inline fun compareTo(v: Float, delta: Float = 0.0f) = Mat2(
x.compareTo(v, delta),
y.compareTo(v, delta)
)
inline fun equals(v: Float, delta: Float = 0.0f) = x.equals(v, delta) && y.equals(v, delta)
operator fun times(m: Mat2) = Mat2( operator fun times(m: Mat2) = Mat2(
Float2( Float2(
@@ -89,12 +103,18 @@ data class Mat2(
) )
) )
inline fun compareTo(m: Mat2, delta: Float = 0.0f) = Mat2(
x.compareTo(m.x, delta),
y.compareTo(m.y, delta)
)
inline fun equals(m: Mat2, delta: Float = 0.0f) = x.equals(m.x, delta) && y.equals(m.y, delta)
operator fun times(v: Float2) = Float2( operator fun times(v: Float2) = Float2(
x.x * v.x + y.x * v.y, x.x * v.x + y.x * v.y,
x.y * v.x + y.y * v.y, x.y * v.x + y.y * v.y,
) )
fun toFloatArray() = floatArrayOf( fun toFloatArray() = floatArrayOf(
x.x, y.x, x.x, y.x,
x.y, y.y x.y, y.y
@@ -106,7 +126,6 @@ data class Mat2(
|${x.y} ${y.y}| |${x.y} ${y.y}|
""".trimIndent() """.trimIndent()
} }
} }
data class Mat3( data class Mat3(
@@ -162,6 +181,14 @@ data class Mat3(
operator fun minus(v: Float) = Mat3(x - v, y - v, z - v) operator fun minus(v: Float) = Mat3(x - v, y - v, z - v)
operator fun times(v: Float) = Mat3(x * v, y * v, z * v) operator fun times(v: Float) = Mat3(x * v, y * v, z * v)
operator fun div(v: Float) = Mat3(x / v, y / v, z / v) operator fun div(v: Float) = Mat3(x / v, y / v, z / v)
inline fun compareTo(v: Float, delta: Float = 0.0f) = Mat3(
x.compareTo(v, delta),
y.compareTo(v, delta),
z.compareTo(v, delta)
)
inline fun equals(v: Float, delta: Float = 0.0f) =
x.equals(v, delta) && y.equals(v, delta) && z.equals(v, delta)
operator fun times(m: Mat3) = Mat3( operator fun times(m: Mat3) = Mat3(
Float3( Float3(
@@ -181,6 +208,15 @@ data class Mat3(
) )
) )
inline fun compareTo(m: Mat3, delta: Float = 0.0f) = Mat3(
x.compareTo(m.x, delta),
y.compareTo(m.y, delta),
z.compareTo(m.z, delta)
)
inline fun equals(m: Mat3, delta: Float = 0.0f) =
x.equals(m.x, delta) && y.equals(m.y, delta) && z.equals(m.z, delta)
operator fun times(v: Float3) = Float3( operator fun times(v: Float3) = Float3(
x.x * v.x + y.x * v.y + z.x * v.z, x.x * v.x + y.x * v.y + z.x * v.z,
x.y * v.x + y.y * v.y + z.y * v.z, x.y * v.x + y.y * v.y + z.y * v.z,
@@ -212,6 +248,7 @@ data class Mat4(
constructor(m: Mat4) : this(m.x.copy(), m.y.copy(), m.z.copy(), m.w.copy()) constructor(m: Mat4) : this(m.x.copy(), m.y.copy(), m.z.copy(), m.w.copy())
companion object { companion object {
fun of(vararg a: Float): Mat4 { fun of(vararg a: Float): Mat4 {
require(a.size >= 16) require(a.size >= 16)
return Mat4( return Mat4(
@@ -302,6 +339,15 @@ data class Mat4(
operator fun minus(v: Float) = Mat4(x - v, y - v, z - v, w - v) operator fun minus(v: Float) = Mat4(x - v, y - v, z - v, w - v)
operator fun times(v: Float) = Mat4(x * v, y * v, z * v, w * v) operator fun times(v: Float) = Mat4(x * v, y * v, z * v, w * v)
operator fun div(v: Float) = Mat4(x / v, y / v, z / v, w / v) operator fun div(v: Float) = Mat4(x / v, y / v, z / v, w / v)
inline fun compareTo(v: Float, delta: Float = 0.0f) = Mat4(
x.compareTo(v, delta),
y.compareTo(v, delta),
z.compareTo(v, delta),
w.compareTo(v, delta)
)
inline fun equals(v: Float, delta: Float = 0.0f) =
x.equals(v, delta) && y.equals(v, delta) && z.equals(v, delta) && w.equals(v, delta)
operator fun times(m: Mat4) = Mat4( operator fun times(m: Mat4) = Mat4(
Float4( Float4(
@@ -330,6 +376,16 @@ data class Mat4(
) )
) )
inline fun compareTo(m: Mat4, delta: Float = 0.0f) = Mat4(
x.compareTo(m.x, delta),
y.compareTo(m.y, delta),
z.compareTo(m.z, delta),
w.compareTo(m.w, delta)
)
inline fun equals(m: Mat4, delta: Float = 0.0f) =
x.equals(m.x, delta) && y.equals(m.y, delta) && z.equals(m.z, delta) && w.equals(m.w, delta)
operator fun times(v: Float4) = Float4( operator fun times(v: Float4) = Float4(
x.x * v.x + y.x * v.y + z.x * v.z+ w.x * v.w, x.x * v.x + y.x * v.y + z.x * v.z+ w.x * v.w,
x.y * v.x + y.y * v.y + z.y * v.z+ w.y * v.w, x.y * v.x + y.y * v.y + z.y * v.z+ w.y * v.w,
@@ -337,6 +393,26 @@ data class Mat4(
x.w * v.x + y.w * v.y + z.w * v.z+ w.w * v.w x.w * v.x + y.w * v.y + z.w * v.z+ w.w * v.w
) )
/**
* Get the Euler angles in degrees from this rotation Matrix
*
* Don't forget to extract the rotation with [rotation] if this is a transposed matrix
*
* @param order The order in which to apply rotations.
* Default is [RotationsOrder.ZYX] which means that the object will first be rotated around its Z
* axis, then its Y axis and finally its X axis.
*
* @see eulerAngles
*/
fun toEulerAngles(order: RotationsOrder = RotationsOrder.ZYX) = eulerAngles(this, order)
/**
* Get the [Quaternion] from this rotation Matrix
*
* Don't forget to extract the rotation with [rotation] if this is a transposed matrix
*
* @see quaternion
*/
fun toQuaternion() = quaternion(this) fun toQuaternion() = quaternion(this)
fun toFloatArray() = floatArrayOf( fun toFloatArray() = floatArrayOf(
@@ -356,6 +432,78 @@ data class Mat4(
} }
} }
inline fun equal(a: Mat2, b: Float, delta: Float = 0.0f) = Bool2(
a.x.equals(b, delta),
a.y.equals(b, delta)
)
inline fun equal(a: Mat2, b: Mat2, delta: Float = 0.0f) = Bool2(
a.x.equals(b.x, delta),
a.y.equals(b.y, delta)
)
inline fun notEqual(a: Mat2, b: Float, delta: Float = 0.0f) = Bool2(
!a.x.equals(b, delta),
!a.y.equals(b, delta)
)
inline fun notEqual(a: Mat2, b: Mat2, delta: Float = 0.0f) = Bool2(
!a.x.equals(b.x, delta),
!a.y.equals(b.y, delta)
)
inline fun equal(a: Mat3, b: Float, delta: Float = 0.0f) = Bool3(
a.x.equals(b, delta),
a.y.equals(b, delta),
a.z.equals(b, delta)
)
inline fun equal(a: Mat3, b: Mat3, delta: Float = 0.0f) = Bool3(
a.x.equals(b.x, delta),
a.y.equals(b.y, delta),
a.z.equals(b.z, delta)
)
inline fun notEqual(a: Mat3, b: Float, delta: Float = 0.0f) = Bool3(
!a.x.equals(b, delta),
!a.y.equals(b, delta),
!a.z.equals(b, delta)
)
inline fun notEqual(a: Mat3, b: Mat3, delta: Float = 0.0f) = Bool3(
!a.x.equals(b.x, delta),
!a.y.equals(b.y, delta),
!a.z.equals(b.z, delta)
)
inline fun equal(a: Mat4, b: Float, delta: Float = 0.0f) = Bool4(
a.x.equals(b, delta),
a.y.equals(b, delta),
a.z.equals(b, delta),
a.w.equals(b, delta)
)
inline fun equal(a: Mat4, b: Mat4, delta: Float = 0.0f) = Bool4(
a.x.equals(b.x, delta),
a.y.equals(b.y, delta),
a.z.equals(b.z, delta),
a.w.equals(b.w, delta)
)
inline fun notEqual(a: Mat4, b: Float, delta: Float = 0.0f) = Bool4(
!a.x.equals(b, delta),
!a.y.equals(b, delta),
!a.z.equals(b, delta),
!a.w.equals(b, delta)
)
inline fun notEqual(a: Mat4, b: Mat4, delta: Float = 0.0f) = Bool4(
!a.x.equals(b.x, delta),
!a.y.equals(b.y, delta),
!a.z.equals(b.z, delta),
!a.w.equals(b.w, delta)
)
fun transpose(m: Mat2) = Mat2( fun transpose(m: Mat2) = Mat2(
Float2(m.x.x, m.y.x), Float2(m.x.x, m.y.x),
Float2(m.x.y, m.y.y) Float2(m.x.y, m.y.y)
@@ -494,14 +642,7 @@ fun rotation(m: Mat4) = Mat4(normalize(m.right), normalize(m.up), normalize(m.fo
*/ */
fun rotation(d: Float3, order: RotationsOrder = RotationsOrder.ZYX): Mat4 { fun rotation(d: Float3, order: RotationsOrder = RotationsOrder.ZYX): Mat4 {
val r = transform(d, ::radians) val r = transform(d, ::radians)
return when(order) { return rotation(r[order.yaw], r[order.pitch], r[order.roll], order)
RotationsOrder.XZY -> rotation(r.x, r.z, r.y)
RotationsOrder.XYZ -> rotation(r.x, r.y, r.z)
RotationsOrder.YXZ -> rotation(r.y, r.x, r.z)
RotationsOrder.YZX -> rotation(r.y, r.z, r.x)
RotationsOrder.ZYX -> rotation(r.z, r.y, r.x)
RotationsOrder.ZXY -> rotation(r.z, r.x, r.y)
}
} }
/** /**
@@ -599,13 +740,93 @@ fun rotation(quaternion: Quaternion): Mat4 {
Float4( Float4(
2.0f * (n.x * n.z + n.y * n.w), 2.0f * (n.x * n.z + n.y * n.w),
2.0f * (n.y * n.z - n.x * n.w), 2.0f * (n.y * n.z - n.x * n.w),
1.0f - 2.0f * (n.x * n.x + n.y * n.y), 1.0f - 2.0f * (n.x * n.x + n.y * n.y)
) )
) )
} }
/** /**
* Extract Quaternion rotation from a Matrix * Get the Euler angles in degrees from a rotation Matrix
*
* @param m The rotation matrix.
* Don't forget to extract the rotation with [rotation] if it's transposed
* @param order The order in which to apply rotations.
* Default is [RotationsOrder.ZYX] which means that the object will first be rotated around its Z
* axis, then its Y axis and finally its X axis.
*/
fun eulerAngles(m: Mat4, order: RotationsOrder = RotationsOrder.ZYX): Float3 {
// We need to more simplify this with RotationsOrder VectorComponents mapped to MatrixColumn
return transform(Float3().apply {
when (order) {
RotationsOrder.XYZ -> {
this[order.pitch] = asin(clamp(m.z.x, -1.0f, 1.0f))
if (abs(m.z.x) < 0.9999999f) {
this[order.yaw] = atan2(-m.z.y, m.z.z)
this[order.roll] = atan2(-m.y.x, m.x.x)
} else {
this[order.yaw] = atan2(m.y.z, m.y.y)
this[order.roll] = 0.0f
}
}
RotationsOrder.XZY -> {
this[order.pitch] = asin(-clamp(m.y.x, -1.0f, 1.0f))
if (abs(m.y.x) < 0.9999999f) {
this[order.yaw] = atan2(m.y.z, m.y.y)
this[order.roll] = atan2(m.z.x, m.x.x)
} else {
this[order.yaw] = atan2(-m.z.y, m.z.z)
this[order.roll] = 0.0f
}
}
RotationsOrder.YXZ -> {
this[order.pitch] = asin(-clamp(m.z.y, -1.0f, 1.0f))
if (abs(m.z.y) < 0.9999999f) {
this[order.yaw] = atan2(m.z.x, m.z.z)
this[order.roll] = atan2(m.x.y, m.y.y)
} else {
this[order.yaw] = atan2(-m.x.z, m.x.x)
this[order.roll] = 0.0f
}
}
RotationsOrder.YZX -> {
this[order.pitch] = asin(clamp(m.x.y, -1.0f, 1.0f))
if (abs(m.x.y) < 0.9999999f) {
this[order.roll] = atan2(-m.z.y, m.y.y)
this[order.yaw] = atan2(-m.x.z, m.x.x)
} else {
this[order.roll] = 0.0f
this[order.yaw] = atan2(m.z.x, m.z.z)
}
}
RotationsOrder.ZXY -> {
this[order.pitch] = asin(clamp(m.y.z, -1.0f, 1.0f))
if (abs(m.y.z) < 0.9999999f) {
this[order.roll] = atan2(-m.x.z, m.z.z)
this[order.yaw] = atan2(-m.y.x, m.y.y)
} else {
this[order.roll] = 0.0f
this[order.yaw] = atan2(m.x.y, m.x.x)
}
}
RotationsOrder.ZYX -> {
this[order.pitch] = asin(-clamp(m.x.z, -1.0f, 1.0f))
if (abs(m.x.z) < 0.9999999f) {
this[order.roll] = atan2(m.y.z, m.z.z)
this[order.yaw] = atan2(m.x.y, m.x.x)
} else {
this[order.roll] = 0.0f
this[order.yaw] = atan2(-m.y.x, m.y.y)
}
}
}
}, ::degrees)
}
/**
* Get the [Quaternion] from a rotation Matrix
*
* @param m The rotation matrix.
* Don't forget to extract the rotation with [rotation] if it's transposed
*/ */
fun quaternion(m: Mat4): Quaternion { fun quaternion(m: Mat4): Quaternion {
val trace = m.x.x + m.y.y + m.z.z val trace = m.x.x + m.y.y + m.z.z
@@ -673,9 +894,14 @@ fun perspective(fov: Float, ratio: Float, near: Float, far: Float): Mat4 {
} }
fun ortho(l: Float, r: Float, b: Float, t: Float, n: Float, f: Float) = Mat4( fun ortho(l: Float, r: Float, b: Float, t: Float, n: Float, f: Float) = Mat4(
Float4(x = 2.0f / (r - 1.0f)), Float4(x = 2.0f / (r - l)),
Float4(y = 2.0f / (t - b)), Float4(y = 2.0f / (t - b)),
Float4(z = -2.0f / (f - n)), Float4(z = -2.0f / (f - n)),
Float4(-(r + l) / (r - l), -(t + b) / (t - b), -(f + n) / (f - n), 1.0f) Float4(
-(r + l) / (r - l),
-(t + b) / (t - b),
-(f + n) / (f - n),
1.0f
)
) )
@@ -191,7 +191,7 @@ class ModelViewer(
asset = assetLoader.createAsset(buffer) asset = assetLoader.createAsset(buffer)
asset?.let { asset -> asset?.let { asset ->
resourceLoader.asyncBeginLoad(asset) resourceLoader.asyncBeginLoad(asset)
animator = asset.getInstance().animator animator = asset.instance.animator
asset.releaseSourceData() asset.releaseSourceData()
} }
} }
@@ -214,7 +214,7 @@ class ModelViewer(
resourceLoader.addResourceData(uri, resourceBuffer) resourceLoader.addResourceData(uri, resourceBuffer)
} }
resourceLoader.asyncBeginLoad(asset) resourceLoader.asyncBeginLoad(asset)
animator = asset.getInstance().animator animator = asset.instance.animator
asset.releaseSourceData() asset.releaseSourceData()
} }
} }
@@ -311,7 +311,7 @@ class ModelViewer(
var count = 0 var count = 0
val popRenderables = { count = asset.popRenderables(readyRenderables); count != 0 } val popRenderables = { count = asset.popRenderables(readyRenderables); count != 0 }
while (popRenderables()) { while (popRenderables()) {
for (i in 0..count - 1) { for (i in 0 until count) {
val ri = rcm.getInstance(readyRenderables[i]) val ri = rcm.getInstance(readyRenderables[i])
rcm.setScreenSpaceContactShadows(ri, true) rcm.setScreenSpaceContactShadows(ri, true)
} }
@@ -371,7 +371,7 @@ class ModelViewer(
resourceLoader.addResourceData(uri, buffer) resourceLoader.addResourceData(uri, buffer)
} }
resourceLoader.asyncBeginLoad(asset) resourceLoader.asyncBeginLoad(asset)
animator = asset.getInstance().animator animator = asset.instance.animator
asset.releaseSourceData() asset.releaseSourceData()
} }
} }
@@ -405,9 +405,19 @@ class ModelViewer(
view.viewport = Viewport(0, 0, width, height) view.viewport = Viewport(0, 0, width, height)
cameraManipulator.setViewport(width, height) cameraManipulator.setViewport(width, height)
updateCameraProjection() updateCameraProjection()
synchronizePendingFrames(engine)
} }
} }
private fun synchronizePendingFrames(engine: Engine) {
// Wait for all pending frames to be processed before returning. This is to
// avoid a race between the surface being resized before pending frames are
// rendered into it.
val fence = engine.createFence()
fence.wait(Fence.Mode.FLUSH, Fence.WAIT_FOR_EVER)
engine.destroyFence(fence)
}
companion object { companion object {
private val kDefaultObjectPosition = Float3(0.0f, 0.0f, -4.0f) private val kDefaultObjectPosition = Float3(0.0f, 0.0f, -4.0f)
} }
@@ -33,9 +33,9 @@ data class Quaternion(
var x: Float = 0.0f, var x: Float = 0.0f,
var y: Float = 0.0f, var y: Float = 0.0f,
var z: Float = 0.0f, var z: Float = 0.0f,
var w: Float = 0.0f) { var w: Float = 1.0f) {
constructor(v: Float3, w: Float = 0.0f) : this(v.x, v.y, v.z, w) constructor(v: Float3, w: Float = 1.0f) : this(v.x, v.y, v.z, w)
constructor(v: Float4) : this(v.x, v.y, v.z, v.w) constructor(v: Float4) : this(v.x, v.y, v.z, v.w)
constructor(q: Quaternion) : this(q.x, q.y, q.z, q.w) constructor(q: Quaternion) : this(q.x, q.y, q.z, q.w)
@@ -52,42 +52,84 @@ data class Quaternion(
} }
/** /**
* Construct a Quaternion from Euler angles using YPR around ZYX respectively * Construct a Quaternion from Euler angles using YPR around a specified order
* *
* The Euler angles are applied in ZYX order. * Uses intrinsic Tait-Bryan angles. This means that rotations are performed with respect to
* i.e: a vector is first rotated about X (roll) then Y (pitch) and then Z (yaw). * the local coordinate system.
* That is, for order 'XYZ', the rotation is first around the X axis (which is the same as
* the world-X axis), then around local-Y (which may now be different from the world
* Y-axis), then local-Z (which may be different from the world Z-axis)
* *
* @param d Per axis Euler angles in degrees * @param d Per axis Euler angles in degrees
* Yaw, pitch, roll (YPR) are taken accordingly to the rotations order input.
* @param order The order in which to apply rotations.
* Default is [RotationsOrder.ZYX] which means that the object will first be rotated around
* its Z axis, then its Y axis and finally its X axis.
*/ */
fun fromEuler(d: Float3): Quaternion { fun fromEuler(d: Float3, order: RotationsOrder = RotationsOrder.ZYX): Quaternion {
val r = transform(d, ::radians) val r = transform(d, ::radians)
return fromEulerZYX(r.z, r.y, r.x) return fromEuler(r[order.yaw], r[order.pitch], r[order.roll], order)
} }
/** /**
* Construct a Quaternion from Euler angles using YPR around ZYX respectively * Construct a Quaternion from Euler yaw, pitch, roll around a specified order.
* *
* The Euler angles are applied in ZYX order. * @param roll about 1st rotation axis in radians. Z in case of ZYX order
* i.e: a vector is first rotated about X (roll) then Y (pitch) and then Z (yaw). * @param pitch about 2nd rotation axis in radians. Y in case of ZYX order
* * @param yaw about 3rd rotation axis in radians. X in case of ZYX order
* @param roll about X axis in radians * @param order The order in which to apply rotations.
* @param pitch about Y axis in radians * Default is [RotationsOrder.ZYX] which means that the object will first be rotated around its Z
* @param yaw about Z axis in radians * axis, then its Y axis and finally its X axis.
*/ */
fun fromEulerZYX(yaw: Float = 0.0f, pitch: Float = 0.0f, roll: Float = 0.0f): Quaternion { fun fromEuler(
val cy = cos(yaw * 0.5f) yaw: Float = 0.0f,
val sy = sin(yaw * 0.5f) pitch: Float = 0.0f,
val cp = cos(pitch * 0.5f) roll: Float = 0.0f,
val sp = sin(pitch * 0.5f) order: RotationsOrder = RotationsOrder.ZYX
val cr = cos(roll * 0.5f) ): Quaternion {
val sr = sin(roll * 0.5f) val c1 = cos(yaw * 0.5f)
val s1 = sin(yaw * 0.5f)
return Quaternion( val c2 = cos(pitch * 0.5f)
sr * cp * cy - cr * sp * sy, val s2 = sin(pitch * 0.5f)
cr * sp * cy + sr * cp * sy, val c3 = cos(roll * 0.5f)
cr * cp * sy - sr * sp * cy, val s3 = sin(roll * 0.5f)
cr * cp * cy + sr * sp * sy return when (order) {
) RotationsOrder.XZY -> Quaternion(
s1 * c2 * c3 - c1 * s2 * s3,
c1 * c2 * s3 - s1 * s2 * c3,
s1 * c2 * s3 + c1 * s2 * c3,
s1 * s2 * s3 + c1 * c2 * c3)
RotationsOrder.XYZ -> Quaternion(
s1 * c2 * c3 + s2 * s3 * c1,
s2 * c1 * c3 - s1 * s3 * c2,
s1 * s2 * c3 + s3 * c1 * c2,
c1 * c2 * c3 - s1 * s2 * s3
)
RotationsOrder.YXZ -> Quaternion(
s1 * c2 * s3 + c1 * s2 * c3,
s1 * c2 * c3 - c1 * s2 * s3,
c1 * c2 * s3 - s1 * s2 * c3,
s1 * s2 * s3 + c1 * c2 * c3
)
RotationsOrder.YZX -> Quaternion(
s1 * s2 * c3 + c1 * c2 * s3,
s1 * c2 * c3 + c1 * s2 * s3,
c1 * s2 * c3 - s1 * c2 * s3,
c1 * c2 * c3 - s1 * s2 * s3
)
RotationsOrder.ZYX -> Quaternion(
c1 * c2 * s3 - s1 * s2 * c3,
s1 * c2 * s3 + c1 * s2 * c3,
s1 * c2 * c3 - c1 * s2 * s3,
s1 * s2 * s3 + c1 * c2 * c3
)
RotationsOrder.ZXY -> Quaternion(
c1 * s2 * c3 - s1 * c2 * s3,
s1 * s2 * c3 + c1 * c2 * s3,
s1 * c2 * c3 + c1 * s2 * s3,
c1 * c2 * c3 - s1 * s2 * s3
)
}
} }
} }
@@ -222,16 +264,44 @@ data class Quaternion(
inline operator fun minus(v: Float) = Quaternion(x - v, y - v, z - v, w - v) inline operator fun minus(v: Float) = Quaternion(x - v, y - v, z - v, w - v)
inline operator fun times(v: Float) = Quaternion(x * v, y * v, z * v, w * v) inline operator fun times(v: Float) = Quaternion(x * v, y * v, z * v, w * v)
inline operator fun div(v: Float) = Quaternion(x / v, y / v, z / v, w / v) inline operator fun div(v: Float) = Quaternion(x / v, y / v, z / v, w / v)
inline fun compareTo(v: Float, delta: Float = 0.0f) = Float4(
x.compareTo(v, delta),
y.compareTo(v, delta),
z.compareTo(v, delta),
w.compareTo(v, delta)
)
inline fun equals(v: Float, delta: Float = 0.0f) = Bool4(
x.equals(v, delta),
y.equals(v, delta),
z.equals(v, delta),
w.equals(v, delta)
)
inline operator fun times(v: Float3) = (this * Quaternion(v, 0.0f) * inverse(this)).xyz inline operator fun times(v: Float3) = (this * Quaternion(v, 0.0f) * inverse(this)).xyz
inline operator fun plus(q: Quaternion) = Quaternion(x + q.x, y + q.y, z + q.z, w + q.w) inline operator fun plus(q: Quaternion) = Quaternion(x + q.x, y + q.y, z + q.z, w + q.w)
inline operator fun minus(q: Quaternion) = Quaternion(x - q.x, y - q.y, z - q.z, w - q.w) inline operator fun minus(q: Quaternion) = Quaternion(x - q.x, y - q.y, z - q.z, w - q.w)
inline operator fun times(q: Quaternion) = Quaternion( inline operator fun times(q: Quaternion) = Quaternion(
w * q.x + x * q.w + y * q.z - z * q.y, w * q.x + x * q.w + y * q.z - z * q.y,
w * q.y - x * q.z + y * q.w + z * q.x, w * q.y - x * q.z + y * q.w + z * q.x,
w * q.z + x * q.y - y * q.x + z * q.w, w * q.z + x * q.y - y * q.x + z * q.w,
w * q.w - x * q.x - y * q.y - z * q.z) w * q.w - x * q.x - y * q.y - z * q.z
)
inline fun compareTo(v: Float4, delta: Float = 0.0f) = Float4(
x.compareTo(v.x, delta),
y.compareTo(v.y, delta),
z.compareTo(v.z, delta),
w.compareTo(v.w, delta)
)
inline fun equals(v: Float4, delta: Float = 0.0f) = Bool4(
x.equals(v.x, delta),
y.equals(v.y, delta),
z.equals(v.z, delta),
w.equals(v.w, delta)
)
inline fun transform(block: (Float) -> Float): Quaternion { inline fun transform(block: (Float) -> Float): Quaternion {
x = block(x) x = block(x)
@@ -253,6 +323,103 @@ inline operator fun Float.minus(q: Quaternion) = Quaternion(this - q.x, this - q
inline operator fun Float.times(q: Quaternion) = Quaternion(this * q.x, this * q.y, this * q.z, this * q.w) inline operator fun Float.times(q: Quaternion) = Quaternion(this * q.x, this * q.y, this * q.z, this * q.w)
inline operator fun Float.div(q: Quaternion) = Quaternion(this / q.x, this / q.y, this / q.z, this / q.w) inline operator fun Float.div(q: Quaternion) = Quaternion(this / q.x, this / q.y, this / q.z, this / q.w)
inline fun lessThan(a: Quaternion, b: Float) = Bool4(
a.x < b,
a.y < b,
a.z < b,
a.w < b
)
inline fun lessThan(a: Quaternion, b: Quaternion) = Bool4(
a.x < b.x,
a.y < b.y,
a.z < b.z,
a.w < b.w
)
inline fun lessThanEqual(a: Quaternion, b: Float) = Bool4(
a.x <= b,
a.y <= b,
a.z <= b,
a.w <= b
)
inline fun lessThanEqual(a: Quaternion, b: Quaternion) = Bool4(
a.x <= b.x,
a.y <= b.y,
a.z <= b.z,
a.w <= b.w
)
inline fun greaterThan(a: Quaternion, b: Float) = Bool4(
a.x > b,
a.y > b,
a.z > b,
a.w > b
)
inline fun greaterThan(a: Quaternion, b: Quaternion) = Bool4(
a.x > b.y,
a.y > b.y,
a.z > b.z,
a.w > b.w
)
inline fun greaterThanEqual(a: Quaternion, b: Float) = Bool4(
a.x >= b,
a.y >= b,
a.z >= b,
a.w >= b
)
inline fun greaterThanEqual(a: Quaternion, b: Quaternion) = Bool4(
a.x >= b.x,
a.y >= b.y,
a.z >= b.z,
a.w >= b.w
)
inline fun equal(a: Quaternion, b: Float, delta: Float = 0.0f) = Bool4(
a.x.equals(b, delta),
a.y.equals(b, delta),
a.z.equals(b, delta),
a.w.equals(b, delta)
)
inline fun equal(a: Quaternion, b: Quaternion, delta: Float = 0.0f) = Bool4(
a.x.equals(b.x, delta),
a.y.equals(b.y, delta),
a.z.equals(b.z, delta),
a.w.equals(b.w, delta)
)
inline fun notEqual(a: Quaternion, b: Float, delta: Float = 0.0f) = Bool4(
!a.x.equals(b, delta),
!a.y.equals(b, delta),
!a.z.equals(b, delta),
!a.w.equals(b, delta)
)
inline fun notEqual(a: Quaternion, b: Quaternion, delta: Float = 0.0f) = Bool4(
!a.x.equals(b.x, delta),
!a.y.equals(b.y, delta),
!a.z.equals(b.z, delta),
!a.w.equals(b.w, delta)
)
inline infix fun Quaternion.lt(b: Float) = Bool4(x < b, y < b, z < b, w < b)
inline infix fun Quaternion.lt(b: Float4) = Bool4(x < b.x, y < b.y, z < b.z, w < b.w)
inline infix fun Quaternion.lte(b: Float) = Bool4(x <= b, y <= b, z <= b, w <= b)
inline infix fun Quaternion.lte(b: Float4) = Bool4(x <= b.x, y <= b.y, z <= b.z, w <= b.w)
inline infix fun Quaternion.gt(b: Float) = Bool4(x > b, y > b, z > b, w > b)
inline infix fun Quaternion.gt(b: Float4) = Bool4(x > b.x, y > b.y, z > b.z, w > b.w)
inline infix fun Quaternion.gte(b: Float) = Bool4(x >= b, y >= b, z >= b, w >= b)
inline infix fun Quaternion.gte(b: Float4) = Bool4(x >= b.x, y >= b.y, z >= b.z, w >= b.w)
inline infix fun Quaternion.eq(b: Float) = Bool4(x == b, y == b, z == b, w == b)
inline infix fun Quaternion.eq(b: Float4) = Bool4(x == b.x, y == b.y, z == b.z, w == b.w)
inline infix fun Quaternion.neq(b: Float) = Bool4(x != b, y != b, z != b, w != b)
inline infix fun Quaternion.neq(b: Float4) = Bool4(x != b.x, y != b.y, z != b.z, w != b.w)
inline fun abs(q: Quaternion) = Quaternion(abs(q.x), abs(q.y), abs(q.z), abs(q.w)) inline fun abs(q: Quaternion) = Quaternion(abs(q.x), abs(q.y), abs(q.z), abs(q.w))
inline fun length(q: Quaternion) = sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w) inline fun length(q: Quaternion) = sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w)
inline fun length2(q: Quaternion) = q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w inline fun length2(q: Quaternion) = q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w
@@ -278,6 +445,10 @@ fun cross(a: Quaternion, b: Quaternion): Quaternion {
return Quaternion(m.x, m.y, m.z, 0.0f) return Quaternion(m.x, m.y, m.z, 0.0f)
} }
fun angle(a: Quaternion, b: Quaternion): Float {
return 2.0f * acos(abs(clamp(dot(a, b), -1.0f, 1.0f)))
}
/** /**
* Spherical linear interpolation between two given orientations * Spherical linear interpolation between two given orientations
* *
@@ -287,36 +458,38 @@ fun cross(a: Quaternion, b: Quaternion): Quaternion {
* @param a The beginning value * @param a The beginning value
* @param b The ending value * @param b The ending value
* @param t The ratio between the two floats * @param t The ratio between the two floats
* @param valueEps Prevent blowing up when slerping between two quaternions that are very near each * @param dotThreshold If the quaternion dot product is greater than this value
* other. Linear interpolation (lerp) is returned in this case. * (i.e. the quaternions are very close to each other), then the quaternions are
* linearly interpolated instead of spherically interpolated.
* *
* @return Interpolated value between the two floats * @return Interpolated value between the two floats
*/ */
fun slerp(a: Quaternion, b: Quaternion, t: Float, valueEps: Float = 0.0000000001f): Quaternion { fun slerp(a: Quaternion, b: Quaternion, t: Float, dotThreshold: Float = 0.9995f): Quaternion {
// could also be computed as: pow(q * inverse(p), t) * p; // could also be computed as: pow(q * inverse(p), t) * p;
val d = dot(a, b) var dot = dot(a, b)
val absd = abs(d) var b1 = b
// If the dot product is negative, then the interpolation won't follow the shortest angular path
// between the two quaterions. In this case, invert the end quaternion to produce an equivalent
// rotation that will give us the path we want.
if (dot < 0.0f) {
dot = -dot
b1 = -b
}
// Prevent blowing up when slerping between two quaternions that are very near each other. // Prevent blowing up when slerping between two quaternions that are very near each other.
if ((1.0f - absd) < valueEps) { return if (dot < dotThreshold) {
return normalize(lerp(if (d < 0.0f) -a else a, b, t)) val angle = acos(dot)
val s = sin(angle)
a * sin((1.0f - t) * angle) / s + b1 * sin(t * angle) / s
} else {
// If the angle is too small, use linear interpolation
nlerp(a, b1, t)
} }
val npq = sqrt(dot(a, a) * dot(b, b)) // ||p|| * ||q||
val acos = acos(clamp(absd / npq, -1.0f, 1.0f))
val acos0 = acos * (1.0f - t)
val acos1 = acos * t
val sina = sin(acos)
if (sina < valueEps) {
return normalize(lerp(a, b, t))
}
val isina = 1.0f / sina
val s0 = sin(acos0) * isina
val s1 = sin(acos1) * isina
// ensure we're taking the "short" side
return normalize(s0 * a + (if (d < 0.0f) -s1 else (s1)) * b)
} }
fun lerp(a: Quaternion, b: Quaternion, t: Float): Quaternion { fun lerp(a: Quaternion, b: Quaternion, t: Float): Quaternion {
return ((1 - t) * a) + (t * b) return ((1.0f - t) * a) + (t * b)
} }
fun nlerp(a: Quaternion, b: Quaternion, t: Float): Quaternion { fun nlerp(a: Quaternion, b: Quaternion, t: Float): Quaternion {
@@ -324,19 +497,12 @@ fun nlerp(a: Quaternion, b: Quaternion, t: Float): Quaternion {
} }
/** /**
* Convert a Quaternion to Euler angles using YPR around ZYX respectively * Convert a Quaternion to Euler angles
* *
* The Euler angles are applied in ZYX order * @param order The order in which to apply rotations.
* Default is [RotationsOrder.ZYX] which means that the object will first be rotated around its Z
* axis, then its Y axis and finally its X axis.
*/ */
fun eulerAngles(q: Quaternion): Float3 { fun eulerAngles(q: Quaternion, order: RotationsOrder = RotationsOrder.ZYX): Float3 {
val nq = normalize(q) return eulerAngles(rotation(q), order)
return Float3(
// roll (x-axis rotation)
degrees(atan2(2.0f * (nq.y * nq.z + nq.w * nq.x),
nq.w * nq.w - nq.x * nq.x - nq.y * nq.y + nq.z * nq.z)),
// pitch (y-axis rotation)
degrees(asin(-2.0f * (nq.x * nq.z - nq.w * nq.y))),
// yaw (z-axis rotation)
degrees(atan2(2.0f * (nq.x * nq.y + nq.w * nq.z),
nq.w * nq.w + nq.x * nq.x - nq.y * nq.y - nq.z * nq.z)))
} }
@@ -28,12 +28,21 @@ const val INV_PI = 1.0f / FPI
const val INV_TWO_PI = INV_PI * 0.5f const val INV_TWO_PI = INV_PI * 0.5f
const val INV_FOUR_PI = INV_PI * 0.25f const val INV_FOUR_PI = INV_PI * 0.25f
inline fun clamp(x: Float, min: Float, max: Float)= if (x < min) min else (if (x > max) max else x) val HALF_ONE = Half(0x3c00.toUShort())
val HALF_TWO = Half(0x4000.toUShort())
inline fun clamp(x: Float, min: Float, max: Float) = if (x < min) min else (if (x > max) max else x)
inline fun clamp(x: Half, min: Half, max: Half) = if (x < min) min else (if (x > max) max else x)
inline fun saturate(x: Float) = clamp(x, 0.0f, 1.0f) inline fun saturate(x: Float) = clamp(x, 0.0f, 1.0f)
inline fun saturate(x: Half) = clamp(x, Half.POSITIVE_ZERO, HALF_ONE)
inline fun mix(a: Float, b: Float, x: Float) = a * (1.0f - x) + b * x inline fun mix(a: Float, b: Float, x: Float) = a * (1.0f - x) + b * x
inline fun mix(a: Half, b: Half, x: Half) = a * (HALF_ONE - x) + b * x
inline fun degrees(v: Float) = v * (180.0f * INV_PI) inline fun degrees(v: Float) = v * (180.0f * INV_PI)
inline fun radians(v: Float) = v * (FPI / 180.0f) inline fun radians(v: Float) = v * (FPI / 180.0f)
@@ -42,4 +51,6 @@ inline fun fract(v: Float) = v % 1
inline fun sqr(v: Float) = v * v inline fun sqr(v: Float) = v * v
inline fun sqr(v: Half) = v * v
inline fun pow(x: Float, y: Float) = (x.toDouble().pow(y.toDouble())).toFloat() inline fun pow(x: Float, y: Float) = (x.toDouble().pow(y.toDouble())).toFloat()
@@ -22,6 +22,8 @@ import kotlin.math.abs
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
import kotlin.math.sqrt import kotlin.math.sqrt
import kotlin.math.acos
import kotlin.math.absoluteValue
enum class VectorComponent { enum class VectorComponent {
X, Y, Z, W, X, Y, Z, W,
@@ -124,11 +126,23 @@ data class Float2(var x: Float = 0.0f, var y: Float = 0.0f) {
inline operator fun minus(v: Float) = Float2(x - v, y - v) inline operator fun minus(v: Float) = Float2(x - v, y - v)
inline operator fun times(v: Float) = Float2(x * v, y * v) inline operator fun times(v: Float) = Float2(x * v, y * v)
inline operator fun div(v: Float) = Float2(x / v, y / v) inline operator fun div(v: Float) = Float2(x / v, y / v)
inline fun compareTo(v: Float, delta: Float = 0.0f) = Float2(
x.compareTo(v, delta),
y.compareTo(v, delta)
)
inline fun equals(v: Float, delta: Float = 0.0f) = x.equals(v, delta) && y.equals(v, delta)
inline operator fun plus(v: Float2) = Float2(x + v.x, y + v.y) inline operator fun plus(v: Float2) = Float2(x + v.x, y + v.y)
inline operator fun minus(v: Float2) = Float2(x - v.x, y - v.y) inline operator fun minus(v: Float2) = Float2(x - v.x, y - v.y)
inline operator fun times(v: Float2) = Float2(x * v.x, y * v.y) inline operator fun times(v: Float2) = Float2(x * v.x, y * v.y)
inline operator fun div(v: Float2) = Float2(x / v.x, y / v.y) inline operator fun div(v: Float2) = Float2(x / v.x, y / v.y)
inline fun compareTo(v: Float2, delta: Float = 0.0f) = Float2(
x.compareTo(v.x, delta),
y.compareTo(v.y, delta)
)
inline fun equals(v: Float2, delta: Float = 0.0f) = x.equals(v.x, delta) && y.equals(v.y, delta)
inline fun transform(block: (Float) -> Float): Float2 { inline fun transform(block: (Float) -> Float): Float2 {
x = block(x) x = block(x)
@@ -291,6 +305,14 @@ data class Float3(var x: Float = 0.0f, var y: Float = 0.0f, var z: Float = 0.0f)
inline operator fun minus(v: Float) = Float3(x - v, y - v, z - v) inline operator fun minus(v: Float) = Float3(x - v, y - v, z - v)
inline operator fun times(v: Float) = Float3(x * v, y * v, z * v) inline operator fun times(v: Float) = Float3(x * v, y * v, z * v)
inline operator fun div(v: Float) = Float3(x / v, y / v, z / v) inline operator fun div(v: Float) = Float3(x / v, y / v, z / v)
inline fun compareTo(v: Float, delta: Float = 0.0f) = Float3(
x.compareTo(v, delta),
y.compareTo(v, delta),
z.compareTo(v, delta)
)
inline fun equals(v: Float, delta: Float = 0.0f) =
x.equals(v, delta) && y.equals(v, delta) && z.equals(v, delta)
inline operator fun plus(v: Float2) = Float3(x + v.x, y + v.y, z) inline operator fun plus(v: Float2) = Float3(x + v.x, y + v.y, z)
inline operator fun minus(v: Float2) = Float3(x - v.x, y - v.y, z) inline operator fun minus(v: Float2) = Float3(x - v.x, y - v.y, z)
@@ -301,6 +323,14 @@ data class Float3(var x: Float = 0.0f, var y: Float = 0.0f, var z: Float = 0.0f)
inline operator fun minus(v: Float3) = Float3(x - v.x, y - v.y, z - v.z) inline operator fun minus(v: Float3) = Float3(x - v.x, y - v.y, z - v.z)
inline operator fun times(v: Float3) = Float3(x * v.x, y * v.y, z * v.z) inline operator fun times(v: Float3) = Float3(x * v.x, y * v.y, z * v.z)
inline operator fun div(v: Float3) = Float3(x / v.x, y / v.y, z / v.z) inline operator fun div(v: Float3) = Float3(x / v.x, y / v.y, z / v.z)
inline fun compareTo(v: Float3, delta: Float = 0.0f) = Float3(
x.compareTo(v.x, delta),
y.compareTo(v.y, delta),
z.compareTo(v.z, delta)
)
inline fun equals(v: Float3, delta: Float = 0.0f) =
x.equals(v.x, delta) && y.equals(v.y, delta) && z.equals(v.z, delta)
inline fun transform(block: (Float) -> Float): Float3 { inline fun transform(block: (Float) -> Float): Float3 {
x = block(x) x = block(x)
@@ -534,6 +564,15 @@ data class Float4(
inline operator fun minus(v: Float) = Float4(x - v, y - v, z - v, w - v) inline operator fun minus(v: Float) = Float4(x - v, y - v, z - v, w - v)
inline operator fun times(v: Float) = Float4(x * v, y * v, z * v, w * v) inline operator fun times(v: Float) = Float4(x * v, y * v, z * v, w * v)
inline operator fun div(v: Float) = Float4(x / v, y / v, z / v, w / v) inline operator fun div(v: Float) = Float4(x / v, y / v, z / v, w / v)
inline fun compareTo(v: Float, delta: Float = 0.0f) = Float4(
x.compareTo(v, delta),
y.compareTo(v, delta),
z.compareTo(v, delta),
w.compareTo(v, delta)
)
inline fun equals(v: Float, delta: Float = 0.0f) =
x.equals(v, delta) && y.equals(v, delta) && z.equals(v, delta) && w.equals(v, delta)
inline operator fun plus(v: Float2) = Float4(x + v.x, y + v.y, z, w) inline operator fun plus(v: Float2) = Float4(x + v.x, y + v.y, z, w)
inline operator fun minus(v: Float2) = Float4(x - v.x, y - v.y, z, w) inline operator fun minus(v: Float2) = Float4(x - v.x, y - v.y, z, w)
@@ -549,6 +588,15 @@ data class Float4(
inline operator fun minus(v: Float4) = Float4(x - v.x, y - v.y, z - v.z, w - v.w) inline operator fun minus(v: Float4) = Float4(x - v.x, y - v.y, z - v.z, w - v.w)
inline operator fun times(v: Float4) = Float4(x * v.x, y * v.y, z * v.z, w * v.w) inline operator fun times(v: Float4) = Float4(x * v.x, y * v.y, z * v.z, w * v.w)
inline operator fun div(v: Float4) = Float4(x / v.x, y / v.y, z / v.z, w / v.w) inline operator fun div(v: Float4) = Float4(x / v.x, y / v.y, z / v.z, w / v.w)
inline fun compareTo(v: Float4, delta: Float = 0.0f) = Float4(
x.compareTo(v.x, delta),
y.compareTo(v.y, delta),
z.compareTo(v.z, delta),
w.compareTo(v.w, delta)
)
inline fun equals(v: Float4, delta: Float = 0.0f) =
x.equals(v.x, delta) && y.equals(v.y, delta) && z.equals(v.z, delta) && w.equals(v.w, delta)
inline fun transform(block: (Float) -> Float): Float4 { inline fun transform(block: (Float) -> Float): Float4 {
x = block(x) x = block(x)
@@ -566,6 +614,12 @@ inline operator fun Float.minus(v: Float2) = Float2(this - v.x, this - v.y)
inline operator fun Float.times(v: Float2) = Float2(this * v.x, this * v.y) inline operator fun Float.times(v: Float2) = Float2(this * v.x, this * v.y)
inline operator fun Float.div(v: Float2) = Float2(this / v.x, this / v.y) inline operator fun Float.div(v: Float2) = Float2(this / v.x, this / v.y)
inline fun Float.compareTo(v: Float, delta: Float): Float = when {
equals(v, delta) -> 0.0f
else -> compareTo(v).toFloat()
}
inline fun Float.equals(v: Float, delta: Float) = (this - v).absoluteValue < delta
inline fun abs(v: Float2) = Float2(abs(v.x), abs(v.y)) inline fun abs(v: Float2) = Float2(abs(v.x), abs(v.y))
inline fun length(v: Float2) = sqrt(v.x * v.x + v.y * v.y) inline fun length(v: Float2) = sqrt(v.x * v.x + v.y * v.y)
inline fun length2(v: Float2) = v.x * v.x + v.y * v.y inline fun length2(v: Float2) = v.x * v.x + v.y * v.y
@@ -583,6 +637,11 @@ fun refract(i: Float2, n: Float2, eta: Float): Float2 {
return if (k < 0.0f) Float2(0.0f) else eta * i - (eta * d + sqrt(k)) * n return if (k < 0.0f) Float2(0.0f) else eta * i - (eta * d + sqrt(k)) * n
} }
inline fun angle(a: Float2, b: Float2): Float {
val l = length(a) * length(b)
return if (l == 0.0f) 0.0f else acos(clamp(dot(a, b) / l, -1.0f, 1.0f))
}
inline fun clamp(v: Float2, min: Float, max: Float): Float2 { inline fun clamp(v: Float2, min: Float, max: Float): Float2 {
return Float2( return Float2(
clamp(v.x, min, max), clamp(v.x, min, max),
@@ -626,10 +685,25 @@ inline fun greaterThan(a: Float2, b: Float) = Bool2(a.x > b, a.y > b)
inline fun greaterThan(a: Float2, b: Float2) = Bool2(a.x > b.y, a.y > b.y) inline fun greaterThan(a: Float2, b: Float2) = Bool2(a.x > b.y, a.y > b.y)
inline fun greaterThanEqual(a: Float2, b: Float) = Bool2(a.x >= b, a.y >= b) inline fun greaterThanEqual(a: Float2, b: Float) = Bool2(a.x >= b, a.y >= b)
inline fun greaterThanEqual(a: Float2, b: Float2) = Bool2(a.x >= b.x, a.y >= b.y) inline fun greaterThanEqual(a: Float2, b: Float2) = Bool2(a.x >= b.x, a.y >= b.y)
inline fun equal(a: Float2, b: Float) = Bool2(a.x == b, a.y == b) inline fun equal(a: Float2, b: Float, delta: Float = 0.0f) = Bool2(
inline fun equal(a: Float2, b: Float2) = Bool2(a.x == b.x, a.y == b.y) a.x.equals(b, delta),
inline fun notEqual(a: Float2, b: Float) = Bool2(a.x != b, a.y != b) a.y.equals(b, delta)
inline fun notEqual(a: Float2, b: Float2) = Bool2(a.x != b.x, a.y != b.y) )
inline fun equal(a: Float2, b: Float2, delta: Float = 0.0f) = Bool2(
a.x.equals(b.x, delta),
a.y.equals(b.y, delta)
)
inline fun notEqual(a: Float2, b: Float, delta: Float = 0.0f) = Bool2(
!a.x.equals(b, delta),
!a.y.equals(b, delta)
)
inline fun notEqual(a: Float2, b: Float2, delta: Float = 0.0f) = Bool2(
!a.x.equals(b.x, delta),
!a.y.equals(b.y, delta)
)
inline infix fun Float2.lt(b: Float) = Bool2(x < b, y < b) inline infix fun Float2.lt(b: Float) = Bool2(x < b, y < b)
inline infix fun Float2.lt(b: Float2) = Bool2(x < b.x, y < b.y) inline infix fun Float2.lt(b: Float2) = Bool2(x < b.x, y < b.y)
@@ -675,6 +749,11 @@ fun refract(i: Float3, n: Float3, eta: Float): Float3 {
return if (k < 0.0f) Float3(0.0f) else eta * i - (eta * d + sqrt(k)) * n return if (k < 0.0f) Float3(0.0f) else eta * i - (eta * d + sqrt(k)) * n
} }
inline fun angle(a: Float3, b: Float3): Float {
val l = length(a) * length(b)
return if (l == 0.0f) 0.0f else acos(clamp(dot(a, b) / l, -1.0f, 1.0f))
}
inline fun clamp(v: Float3, min: Float, max: Float): Float3 { inline fun clamp(v: Float3, min: Float, max: Float): Float3 {
return Float3( return Float3(
clamp(v.x, min, max), clamp(v.x, min, max),
@@ -722,10 +801,29 @@ inline fun greaterThan(a: Float3, b: Float) = Bool3(a.x > b, a.y > b, a.z > b)
inline fun greaterThan(a: Float3, b: Float3) = Bool3(a.x > b.y, a.y > b.y, a.z > b.z) inline fun greaterThan(a: Float3, b: Float3) = Bool3(a.x > b.y, a.y > b.y, a.z > b.z)
inline fun greaterThanEqual(a: Float3, b: Float) = Bool3(a.x >= b, a.y >= b, a.z >= b) inline fun greaterThanEqual(a: Float3, b: Float) = Bool3(a.x >= b, a.y >= b, a.z >= b)
inline fun greaterThanEqual(a: Float3, b: Float3) = Bool3(a.x >= b.x, a.y >= b.y, a.z >= b.z) inline fun greaterThanEqual(a: Float3, b: Float3) = Bool3(a.x >= b.x, a.y >= b.y, a.z >= b.z)
inline fun equal(a: Float3, b: Float) = Bool3(a.x == b, a.y == b, a.z == b) inline fun equal(a: Float3, b: Float, delta: Float = 0.0f) = Bool3(
inline fun equal(a: Float3, b: Float3) = Bool3(a.x == b.x, a.y == b.y, a.z == b.z) a.x.equals(b, delta),
inline fun notEqual(a: Float3, b: Float) = Bool3(a.x != b, a.y != b, a.z != b) a.y.equals(b, delta),
inline fun notEqual(a: Float3, b: Float3) = Bool3(a.x != b.x, a.y != b.y, a.z != b.z) a.z.equals(b, delta)
)
inline fun equal(a: Float3, b: Float3, delta: Float = 0.0f) = Bool3(
a.x.equals(b.x, delta),
a.y.equals(b.y, delta),
a.z.equals(b.z, delta)
)
inline fun notEqual(a: Float3, b: Float, delta: Float = 0.0f) = Bool3(
!a.x.equals(b, delta),
!a.y.equals(b, delta),
!a.z.equals(b, delta)
)
inline fun notEqual(a: Float3, b: Float3, delta: Float = 0.0f) = Bool3(
!a.x.equals(b.x, delta),
!a.y.equals(b.y, delta),
!a.z.equals(b.z, delta)
)
inline infix fun Float3.lt(b: Float) = Bool3(x < b, y < b, z < b) inline infix fun Float3.lt(b: Float) = Bool3(x < b, y < b, z < b)
inline infix fun Float3.lt(b: Float3) = Bool3(x < b.x, y < b.y, z < b.z) inline infix fun Float3.lt(b: Float3) = Bool3(x < b.x, y < b.y, z < b.z)
@@ -807,17 +905,44 @@ inline fun transform(v: Float4, block: (Float) -> Float) = v.copy().transform(bl
inline fun lessThan(a: Float4, b: Float) = Bool4(a.x < b, a.y < b, a.z < b, a.w < b) inline fun lessThan(a: Float4, b: Float) = Bool4(a.x < b, a.y < b, a.z < b, a.w < b)
inline fun lessThan(a: Float4, b: Float4) = Bool4(a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w) inline fun lessThan(a: Float4, b: Float4) = Bool4(a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w)
inline fun lessThanEqual(a: Float4, b: Float) = Bool4(a.x <= b, a.y <= b, a.z <= b, a.w <= b) inline fun lessThanEqual(a: Float4, b: Float) = Bool4(a.x <= b, a.y <= b, a.z <= b, a.w <= b)
inline fun lessThanEqual(a: Float4, b: Float4) = Bool4(a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w) inline fun lessThanEqual(a: Float4, b: Float4) =
Bool4(a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w)
inline fun greaterThan(a: Float4, b: Float) = Bool4(a.x > b, a.y > b, a.z > b, a.w > b) inline fun greaterThan(a: Float4, b: Float) = Bool4(a.x > b, a.y > b, a.z > b, a.w > b)
inline fun greaterThan(a: Float4, b: Float4) = Bool4(a.x > b.y, a.y > b.y, a.z > b.z, a.w > b.w) inline fun greaterThan(a: Float4, b: Float4) = Bool4(a.x > b.y, a.y > b.y, a.z > b.z, a.w > b.w)
inline fun greaterThanEqual(a: Float4, b: Float) = Bool4(a.x >= b, a.y >= b, a.z >= b, a.w >= b) inline fun greaterThanEqual(a: Float4, b: Float) = Bool4(a.x >= b, a.y >= b, a.z >= b, a.w >= b)
inline fun greaterThanEqual(a: Float4, b: Float4) = Bool4(a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w) inline fun greaterThanEqual(a: Float4, b: Float4) =
inline fun equal(a: Float4, b: Float) = Bool4(a.x == b, a.y == b, a.z == b, a.w == b) Bool4(a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w)
inline fun equal(a: Float4, b: Float4) = Bool4(a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w)
inline fun notEqual(a: Float4, b: Float) = Bool4(a.x != b, a.y != b, a.z != b, a.w != b)
inline fun notEqual(a: Float4, b: Float4) = Bool4(a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w)
inline infix fun Float4.lt(b: Float) = Bool4(x < b, y < b, z < b, a < b) inline fun equal(a: Float4, b: Float, delta: Float = 0.0f) = Bool4(
a.x.equals(b, delta),
a.y.equals(b, delta),
a.z.equals(b, delta),
a.w.equals(b, delta)
)
inline fun equal(a: Float4, b: Float4, delta: Float = 0.0f) = Bool4(
a.x.equals(b.x, delta),
a.y.equals(b.y, delta),
a.z.equals(b.z, delta),
a.w.equals(b.w, delta)
)
inline fun notEqual(a: Float4, b: Float, delta: Float = 0.0f) = Bool4(
!a.x.equals(b, delta),
!a.y.equals(b, delta),
!a.z.equals(b, delta),
!a.w.equals(b, delta)
)
inline fun notEqual(a: Float4, b: Float4, delta: Float = 0.0f) = Bool4(
!a.x.equals(b.x, delta),
!a.y.equals(b.y, delta),
!a.z.equals(b.z, delta),
!a.w.equals(b.w, delta)
)
inline infix fun Float4.lt(b: Float) = Bool4(x < b, y < b, z < b, w < b)
inline infix fun Float4.lt(b: Float4) = Bool4(x < b.x, y < b.y, z < b.z, w < b.w) inline infix fun Float4.lt(b: Float4) = Bool4(x < b.x, y < b.y, z < b.z, w < b.w)
inline infix fun Float4.lte(b: Float) = Bool4(x <= b, y <= b, z <= b, w <= b) inline infix fun Float4.lte(b: Float) = Bool4(x <= b, y <= b, z <= b, w <= b)
inline infix fun Float4.lte(b: Float4) = Bool4(x <= b.x, y <= b.y, z <= b.z, w <= b.w) inline infix fun Float4.lte(b: Float4) = Bool4(x <= b.x, y <= b.y, z <= b.z, w <= b.w)
@@ -1277,3 +1402,753 @@ data class Bool4(
set(index4, v) set(index4, v)
} }
} }
data class Half2(var x: Half = Half.POSITIVE_ZERO, var y: Half = Half.POSITIVE_ZERO) {
constructor(v: Half) : this(v, v)
constructor(v: Half2) : this(v.x, v.y)
inline var r: Half
get() = x
set(value) {
x = value
}
inline var g: Half
get() = y
set(value) {
y = value
}
inline var s: Half
get() = x
set(value) {
x = value
}
inline var t: Half
get() = y
set(value) {
y = value
}
inline var xy: Half2
get() = Half2(x, y)
set(value) {
x = value.x
y = value.y
}
inline var rg: Half2
get() = Half2(x, y)
set(value) {
x = value.x
y = value.y
}
inline var st: Half2
get() = Half2(x, y)
set(value) {
x = value.x
y = value.y
}
operator fun get(index: VectorComponent) = when (index) {
VectorComponent.X, VectorComponent.R, VectorComponent.S -> x
VectorComponent.Y, VectorComponent.G, VectorComponent.T -> y
else -> throw IllegalArgumentException("index must be X, Y, R, G, S or T")
}
operator fun get(index1: VectorComponent, index2: VectorComponent): Half2 {
return Half2(get(index1), get(index2))
}
operator fun get(index: Int) = when (index) {
0 -> x
1 -> y
else -> throw IllegalArgumentException("index must be in 0..1")
}
operator fun get(index1: Int, index2: Int) = Half2(get(index1), get(index2))
inline operator fun invoke(index: Int) = get(index - 1)
operator fun set(index: Int, v: Half) = when (index) {
0 -> x = v
1 -> y = v
else -> throw IllegalArgumentException("index must be in 0..1")
}
operator fun set(index1: Int, index2: Int, v: Half) {
set(index1, v)
set(index2, v)
}
operator fun set(index: VectorComponent, v: Half) = when (index) {
VectorComponent.X, VectorComponent.R, VectorComponent.S -> x = v
VectorComponent.Y, VectorComponent.G, VectorComponent.T -> y = v
else -> throw IllegalArgumentException("index must be X, Y, R, G, S or T")
}
operator fun set(index1: VectorComponent, index2: VectorComponent, v: Half) {
set(index1, v)
set(index2, v)
}
operator fun unaryMinus() = Half2(-x, -y)
operator fun inc() = Half2(x++, y++)
operator fun dec() = Half2(x--, y--)
inline operator fun plus(v: Half) = Half2(x + v, y + v)
inline operator fun minus(v: Half) = Half2(x - v, y - v)
inline operator fun times(v: Half) = Half2(x * v, y * v)
inline operator fun div(v: Half) = Half2(x / v, y / v)
inline operator fun plus(v: Half2) = Half2(x + v.x, y + v.y)
inline operator fun minus(v: Half2) = Half2(x - v.x, y - v.y)
inline operator fun times(v: Half2) = Half2(x * v.x, y * v.y)
inline operator fun div(v: Half2) = Half2(x / v.x, y / v.y)
inline fun transform(block: (Half) -> Half): Half2 {
x = block(x)
y = block(y)
return this
}
fun toFloatArray() = floatArrayOf(x.toFloat(), y.toFloat())
}
data class Half3(
var x: Half = Half.POSITIVE_ZERO,
var y: Half = Half.POSITIVE_ZERO,
var z: Half = Half.POSITIVE_ZERO
) {
constructor(v: Half) : this(v, v, v)
constructor(v: Half2, z: Half = Half.POSITIVE_ZERO) : this(v.x, v.y, z)
constructor(v: Half3) : this(v.x, v.y, v.z)
inline var r: Half
get() = x
set(value) {
x = value
}
inline var g: Half
get() = y
set(value) {
y = value
}
inline var b: Half
get() = z
set(value) {
z = value
}
inline var s: Half
get() = x
set(value) {
x = value
}
inline var t: Half
get() = y
set(value) {
y = value
}
inline var p: Half
get() = z
set(value) {
z = value
}
inline var xy: Half2
get() = Half2(x, y)
set(value) {
x = value.x
y = value.y
}
inline var rg: Half2
get() = Half2(x, y)
set(value) {
x = value.x
y = value.y
}
inline var st: Half2
get() = Half2(x, y)
set(value) {
x = value.x
y = value.y
}
inline var rgb: Half3
get() = Half3(x, y, z)
set(value) {
x = value.x
y = value.y
z = value.z
}
inline var xyz: Half3
get() = Half3(x, y, z)
set(value) {
x = value.x
y = value.y
z = value.z
}
inline var stp: Half3
get() = Half3(x, y, z)
set(value) {
x = value.x
y = value.y
z = value.z
}
operator fun get(index: VectorComponent) = when (index) {
VectorComponent.X, VectorComponent.R, VectorComponent.S -> x
VectorComponent.Y, VectorComponent.G, VectorComponent.T -> y
VectorComponent.Z, VectorComponent.B, VectorComponent.P -> z
else -> throw IllegalArgumentException("index must be X, Y, Z, R, G, B, S, T or P")
}
operator fun get(index1: VectorComponent, index2: VectorComponent): Half2 {
return Half2(get(index1), get(index2))
}
operator fun get(
index1: VectorComponent, index2: VectorComponent, index3: VectorComponent): Half3 {
return Half3(get(index1), get(index2), get(index3))
}
operator fun get(index: Int) = when (index) {
0 -> x
1 -> y
2 -> z
else -> throw IllegalArgumentException("index must be in 0..2")
}
operator fun get(index1: Int, index2: Int) = Half2(get(index1), get(index2))
operator fun get(index1: Int, index2: Int, index3: Int): Half3 {
return Half3(get(index1), get(index2), get(index3))
}
inline operator fun invoke(index: Int) = get(index - 1)
operator fun set(index: Int, v: Half) = when (index) {
0 -> x = v
1 -> y = v
2 -> z = v
else -> throw IllegalArgumentException("index must be in 0..2")
}
operator fun set(index1: Int, index2: Int, v: Half) {
set(index1, v)
set(index2, v)
}
operator fun set(index1: Int, index2: Int, index3: Int, v: Half) {
set(index1, v)
set(index2, v)
set(index3, v)
}
operator fun set(index: VectorComponent, v: Half) = when (index) {
VectorComponent.X, VectorComponent.R, VectorComponent.S -> x = v
VectorComponent.Y, VectorComponent.G, VectorComponent.T -> y = v
VectorComponent.Z, VectorComponent.B, VectorComponent.P -> z = v
else -> throw IllegalArgumentException("index must be X, Y, Z, R, G, B, S, T or P")
}
operator fun set(index1: VectorComponent, index2: VectorComponent, v: Half) {
set(index1, v)
set(index2, v)
}
operator fun set(
index1: VectorComponent, index2: VectorComponent, index3: VectorComponent, v: Half) {
set(index1, v)
set(index2, v)
set(index3, v)
}
operator fun unaryMinus() = Half3(-x, -y, -z)
operator fun inc() = Half3(x++, y++, z++)
operator fun dec() = Half3(x--, y--, z--)
inline operator fun plus(v: Half) = Half3(x + v, y + v, z + v)
inline operator fun minus(v: Half) = Half3(x - v, y - v, z - v)
inline operator fun times(v: Half) = Half3(x * v, y * v, z * v)
inline operator fun div(v: Half) = Half3(x / v, y / v, z / v)
inline operator fun plus(v: Half2) = Half3(x + v.x, y + v.y, z)
inline operator fun minus(v: Half2) = Half3(x - v.x, y - v.y, z)
inline operator fun times(v: Half2) = Half3(x * v.x, y * v.y, z)
inline operator fun div(v: Half2) = Half3(x / v.x, y / v.y, z)
inline operator fun plus(v: Half3) = Half3(x + v.x, y + v.y, z + v.z)
inline operator fun minus(v: Half3) = Half3(x - v.x, y - v.y, z - v.z)
inline operator fun times(v: Half3) = Half3(x * v.x, y * v.y, z * v.z)
inline operator fun div(v: Half3) = Half3(x / v.x, y / v.y, z / v.z)
inline fun transform(block: (Half) -> Half): Half3 {
x = block(x)
y = block(y)
z = block(z)
return this
}
fun toFloatArray() = floatArrayOf(x.toFloat(), y.toFloat(), z.toFloat())
}
data class Half4(
var x: Half = Half.POSITIVE_ZERO,
var y: Half = Half.POSITIVE_ZERO,
var z: Half = Half.POSITIVE_ZERO,
var w: Half = Half.POSITIVE_ZERO
) {
constructor(v: Half) : this(v, v, v, v)
constructor(v: Half2, z: Half = Half.POSITIVE_ZERO, w: Half = Half.POSITIVE_ZERO) : this(v.x, v.y, z, w)
constructor(v: Half3, w: Half = Half.POSITIVE_ZERO) : this(v.x, v.y, v.z, w)
constructor(v: Half4) : this(v.x, v.y, v.z, v.w)
inline var r: Half
get() = x
set(value) {
x = value
}
inline var g: Half
get() = y
set(value) {
y = value
}
inline var b: Half
get() = z
set(value) {
z = value
}
inline var a: Half
get() = w
set(value) {
w = value
}
inline var s: Half
get() = x
set(value) {
x = value
}
inline var t: Half
get() = y
set(value) {
y = value
}
inline var p: Half
get() = z
set(value) {
z = value
}
inline var q: Half
get() = w
set(value) {
w = value
}
inline var xy: Half2
get() = Half2(x, y)
set(value) {
x = value.x
y = value.y
}
inline var rg: Half2
get() = Half2(x, y)
set(value) {
x = value.x
y = value.y
}
inline var st: Half2
get() = Half2(x, y)
set(value) {
x = value.x
y = value.y
}
inline var rgb: Half3
get() = Half3(x, y, z)
set(value) {
x = value.x
y = value.y
z = value.z
}
inline var xyz: Half3
get() = Half3(x, y, z)
set(value) {
x = value.x
y = value.y
z = value.z
}
inline var stp: Half3
get() = Half3(x, y, z)
set(value) {
x = value.x
y = value.y
z = value.z
}
inline var rgba: Half4
get() = Half4(x, y, z, w)
set(value) {
x = value.x
y = value.y
z = value.z
w = value.w
}
inline var xyzw: Half4
get() = Half4(x, y, z, w)
set(value) {
x = value.x
y = value.y
z = value.z
w = value.w
}
inline var stpq: Half4
get() = Half4(x, y, z, w)
set(value) {
x = value.x
y = value.y
z = value.z
w = value.w
}
operator fun get(index: VectorComponent) = when (index) {
VectorComponent.X, VectorComponent.R, VectorComponent.S -> x
VectorComponent.Y, VectorComponent.G, VectorComponent.T -> y
VectorComponent.Z, VectorComponent.B, VectorComponent.P -> z
VectorComponent.W, VectorComponent.A, VectorComponent.Q -> w
}
operator fun get(index1: VectorComponent, index2: VectorComponent): Half2 {
return Half2(get(index1), get(index2))
}
operator fun get(
index1: VectorComponent,
index2: VectorComponent,
index3: VectorComponent): Half3 {
return Half3(get(index1), get(index2), get(index3))
}
operator fun get(
index1: VectorComponent,
index2: VectorComponent,
index3: VectorComponent,
index4: VectorComponent): Half4 {
return Half4(get(index1), get(index2), get(index3), get(index4))
}
operator fun get(index: Int) = when (index) {
0 -> x
1 -> y
2 -> z
3 -> w
else -> throw IllegalArgumentException("index must be in 0..3")
}
operator fun get(index1: Int, index2: Int) = Half2(get(index1), get(index2))
operator fun get(index1: Int, index2: Int, index3: Int): Half3 {
return Half3(get(index1), get(index2), get(index3))
}
operator fun get(index1: Int, index2: Int, index3: Int, index4: Int): Half4 {
return Half4(get(index1), get(index2), get(index3), get(index4))
}
inline operator fun invoke(index: Int) = get(index - 1)
operator fun set(index: Int, v: Half) = when (index) {
0 -> x = v
1 -> y = v
2 -> z = v
3 -> w = v
else -> throw IllegalArgumentException("index must be in 0..3")
}
operator fun set(index1: Int, index2: Int, v: Half) {
set(index1, v)
set(index2, v)
}
operator fun set(index1: Int, index2: Int, index3: Int, v: Half) {
set(index1, v)
set(index2, v)
set(index3, v)
}
operator fun set(index1: Int, index2: Int, index3: Int, index4: Int, v: Half) {
set(index1, v)
set(index2, v)
set(index3, v)
set(index4, v)
}
operator fun set(index: VectorComponent, v: Half) = when (index) {
VectorComponent.X, VectorComponent.R, VectorComponent.S -> x = v
VectorComponent.Y, VectorComponent.G, VectorComponent.T -> y = v
VectorComponent.Z, VectorComponent.B, VectorComponent.P -> z = v
VectorComponent.W, VectorComponent.A, VectorComponent.Q -> w = v
}
operator fun set(index1: VectorComponent, index2: VectorComponent, v: Half) {
set(index1, v)
set(index2, v)
}
operator fun set(
index1: VectorComponent, index2: VectorComponent, index3: VectorComponent, v: Half) {
set(index1, v)
set(index2, v)
set(index3, v)
}
operator fun set(
index1: VectorComponent, index2: VectorComponent,
index3: VectorComponent, index4: VectorComponent, v: Half) {
set(index1, v)
set(index2, v)
set(index3, v)
set(index4, v)
}
operator fun unaryMinus() = Half4(-x, -y, -z, -w)
operator fun inc() = Half4(x++, y++, z++, w++)
operator fun dec() = Half4(x--, y--, z--, w--)
inline operator fun plus(v: Half) = Half4(x + v, y + v, z + v, w + v)
inline operator fun minus(v: Half) = Half4(x - v, y - v, z - v, w - v)
inline operator fun times(v: Half) = Half4(x * v, y * v, z * v, w * v)
inline operator fun div(v: Half) = Half4(x / v, y / v, z / v, w / v)
inline operator fun plus(v: Half2) = Half4(x + v.x, y + v.y, z, w)
inline operator fun minus(v: Half2) = Half4(x - v.x, y - v.y, z, w)
inline operator fun times(v: Half2) = Half4(x * v.x, y * v.y, z, w)
inline operator fun div(v: Half2) = Half4(x / v.x, y / v.y, z, w)
inline operator fun plus(v: Half3) = Half4(x + v.x, y + v.y, z + v.z, w)
inline operator fun minus(v: Half3) = Half4(x - v.x, y - v.y, z - v.z, w)
inline operator fun times(v: Half3) = Half4(x * v.x, y * v.y, z * v.z, w)
inline operator fun div(v: Half3) = Half4(x / v.x, y / v.y, z / v.z, w)
inline operator fun plus(v: Half4) = Half4(x + v.x, y + v.y, z + v.z, w + v.w)
inline operator fun minus(v: Half4) = Half4(x - v.x, y - v.y, z - v.z, w - v.w)
inline operator fun times(v: Half4) = Half4(x * v.x, y * v.y, z * v.z, w * v.w)
inline operator fun div(v: Half4) = Half4(x / v.x, y / v.y, z / v.z, w / v.w)
inline fun transform(block: (Half) -> Half): Half4 {
x = block(x)
y = block(y)
z = block(z)
w = block(w)
return this
}
fun toFloatArray() = floatArrayOf(x.toFloat(), y.toFloat(), z.toFloat(), w.toFloat())
}
inline fun min(v: Half2) = min(v.x, v.y)
inline fun min(a: Half2, b: Half2) = Half2(min(a.x, b.x), min(a.y, b.y))
inline fun max(v: Half2) = max(v.x, v.y)
inline fun max(a: Half2, b: Half2) = Half2(max(a.x, b.x), max(a.y, b.y))
inline fun transform(v: Half2, block: (Half) -> Half) = v.copy().transform(block)
inline fun lessThan(a: Half2, b: Half) = Bool2(a.x < b, a.y < b)
inline fun lessThan(a: Half2, b: Half2) = Bool2(a.x < b.x, a.y < b.y)
inline fun lessThanEqual(a: Half2, b: Half) = Bool2(a.x <= b, a.y <= b)
inline fun lessThanEqual(a: Half2, b: Half2) = Bool2(a.x <= b.x, a.y <= b.y)
inline fun greaterThan(a: Half2, b: Half) = Bool2(a.x > b, a.y > b)
inline fun greaterThan(a: Half2, b: Half2) = Bool2(a.x > b.y, a.y > b.y)
inline fun greaterThanEqual(a: Half2, b: Half) = Bool2(a.x >= b, a.y >= b)
inline fun greaterThanEqual(a: Half2, b: Half2) = Bool2(a.x >= b.x, a.y >= b.y)
inline fun equal(a: Half2, b: Half) = Bool2(a.x == b, a.y == b)
inline fun equal(a: Half2, b: Half2) = Bool2(a.x == b.x, a.y == b.y)
inline fun notEqual(a: Half2, b: Half) = Bool2(a.x != b, a.y != b)
inline fun notEqual(a: Half2, b: Half2) = Bool2(a.x != b.x, a.y != b.y)
inline infix fun Half2.lt(b: Half) = Bool2(x < b, y < b)
inline infix fun Half2.lt(b: Half2) = Bool2(x < b.x, y < b.y)
inline infix fun Half2.lte(b: Half) = Bool2(x <= b, y <= b)
inline infix fun Half2.lte(b: Half2) = Bool2(x <= b.x, y <= b.y)
inline infix fun Half2.gt(b: Half) = Bool2(x > b, y > b)
inline infix fun Half2.gt(b: Half2) = Bool2(x > b.x, y > b.y)
inline infix fun Half2.gte(b: Half) = Bool2(x >= b, y >= b)
inline infix fun Half2.gte(b: Half2) = Bool2(x >= b.x, y >= b.y)
inline infix fun Half2.eq(b: Half) = Bool2(x == b, y == b)
inline infix fun Half2.eq(b: Half2) = Bool2(x == b.x, y == b.y)
inline infix fun Half2.neq(b: Half) = Bool2(x != b, y != b)
inline infix fun Half2.neq(b: Half2) = Bool2(x != b.x, y != b.y)
inline operator fun Half.plus(v: Half3) = Half3(this + v.x, this + v.y, this + v.z)
inline operator fun Half.minus(v: Half3) = Half3(this - v.x, this - v.y, this - v.z)
inline operator fun Half.times(v: Half3) = Half3(this * v.x, this * v.y, this * v.z)
inline operator fun Half.div(v: Half3) = Half3(this / v.x, this / v.y, this / v.z)
inline fun abs(v: Half3) = Half3(abs(v.x), abs(v.y), abs(v.z))
inline fun length(v: Half3) = sqrt(v.x * v.x + v.y * v.y + v.z * v.z)
inline fun length2(v: Half3) = v.x * v.x + v.y * v.y + v.z * v.z
inline fun distance(a: Half3, b: Half3) = length(a - b)
inline fun dot(a: Half3, b: Half3) = a.x * b.x + a.y * b.y + a.z * b.z
inline fun cross(a: Half3, b: Half3): Half3 {
return Half3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x)
}
inline infix fun Half3.x(v: Half3): Half3 {
return Half3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x)
}
fun normalize(v: Half3): Half3 {
val l = HALF_ONE / length(v)
return Half3(v.x * l, v.y * l, v.z * l)
}
inline fun reflect(i: Half3, n: Half3) = i - HALF_TWO * dot(n, i) * n
fun refract(i: Half3, n: Half3, eta: Half): Half3 {
val d = dot(n, i)
val k = HALF_ONE - eta * eta * (HALF_ONE - sqr(d))
return if (k < Half.POSITIVE_ZERO) Half3() else eta * i - (eta * d + sqrt(k)) * n
}
inline fun clamp(v: Half3, min: Half, max: Half): Half3 {
return Half3(
clamp(v.x, min, max),
clamp(v.y, min, max),
clamp(v.z, min, max)
)
}
inline fun clamp(v: Half3, min: Half3, max: Half3): Half3 {
return Half3(
clamp(v.x, min.x, max.x),
clamp(v.y, min.y, max.y),
clamp(v.z, min.z, max.z)
)
}
inline fun mix(a: Half3, b: Half3, x: Half): Half3 {
return Half3(
mix(a.x, b.x, x),
mix(a.y, b.y, x),
mix(a.z, b.z, x)
)
}
inline fun mix(a: Half3, b: Half3, x: Half3): Half3 {
return Half3(
mix(a.x, b.x, x.x),
mix(a.y, b.y, x.y),
mix(a.z, b.z, x.z)
)
}
inline fun min(v: Half3) = min(v.x, min(v.y, v.z))
inline fun min(a: Half3, b: Half3) = Half3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z))
inline fun max(v: Half3) = max(v.x, max(v.y, v.z))
inline fun max(a: Half3, b: Half3) = Half3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z))
inline fun transform(v: Half3, block: (Half) -> Half) = v.copy().transform(block)
inline fun lessThan(a: Half3, b: Half) = Bool3(a.x < b, a.y < b, a.z < b)
inline fun lessThan(a: Half3, b: Half3) = Bool3(a.x < b.x, a.y < b.y, a.z < b.z)
inline fun lessThanEqual(a: Half3, b: Half) = Bool3(a.x <= b, a.y <= b, a.z <= b)
inline fun lessThanEqual(a: Half3, b: Half3) = Bool3(a.x <= b.x, a.y <= b.y, a.z <= b.z)
inline fun greaterThan(a: Half3, b: Half) = Bool3(a.x > b, a.y > b, a.z > b)
inline fun greaterThan(a: Half3, b: Half3) = Bool3(a.x > b.y, a.y > b.y, a.z > b.z)
inline fun greaterThanEqual(a: Half3, b: Half) = Bool3(a.x >= b, a.y >= b, a.z >= b)
inline fun greaterThanEqual(a: Half3, b: Half3) = Bool3(a.x >= b.x, a.y >= b.y, a.z >= b.z)
inline fun equal(a: Half3, b: Half) = Bool3(a.x == b, a.y == b, a.z == b)
inline fun equal(a: Half3, b: Half3) = Bool3(a.x == b.x, a.y == b.y, a.z == b.z)
inline fun notEqual(a: Half3, b: Half) = Bool3(a.x != b, a.y != b, a.z != b)
inline fun notEqual(a: Half3, b: Half3) = Bool3(a.x != b.x, a.y != b.y, a.z != b.z)
inline infix fun Half3.lt(b: Half) = Bool3(x < b, y < b, z < b)
inline infix fun Half3.lt(b: Half3) = Bool3(x < b.x, y < b.y, z < b.z)
inline infix fun Half3.lte(b: Half) = Bool3(x <= b, y <= b, z <= b)
inline infix fun Half3.lte(b: Half3) = Bool3(x <= b.x, y <= b.y, z <= b.z)
inline infix fun Half3.gt(b: Half) = Bool3(x > b, y > b, z > b)
inline infix fun Half3.gt(b: Half3) = Bool3(x > b.x, y > b.y, z > b.z)
inline infix fun Half3.gte(b: Half) = Bool3(x >= b, y >= b, z >= b)
inline infix fun Half3.gte(b: Half3) = Bool3(x >= b.x, y >= b.y, z >= b.z)
inline infix fun Half3.eq(b: Half) = Bool3(x == b, y == b, z == b)
inline infix fun Half3.eq(b: Half3) = Bool3(x == b.x, y == b.y, z == b.z)
inline infix fun Half3.neq(b: Half) = Bool3(x != b, y != b, z != b)
inline infix fun Half3.neq(b: Half3) = Bool3(x != b.x, y != b.y, z != b.z)
inline operator fun Half.plus(v: Half4) = Half4(this + v.x, this + v.y, this + v.z, this + v.w)
inline operator fun Half.minus(v: Half4) = Half4(this - v.x, this - v.y, this - v.z, this - v.w)
inline operator fun Half.times(v: Half4) = Half4(this * v.x, this * v.y, this * v.z, this * v.w)
inline operator fun Half.div(v: Half4) = Half4(this / v.x, this / v.y, this / v.z, this / v.w)
inline fun abs(v: Half4) = Half4(abs(v.x), abs(v.y), abs(v.z), abs(v.w))
inline fun length(v: Half4) = sqrt(v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w)
inline fun length2(v: Half4) = v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w
inline fun distance(a: Half4, b: Half4) = length(a - b)
inline fun dot(a: Half4, b: Half4) = a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w
fun normalize(v: Half4): Half4 {
val l = HALF_ONE / length(v)
return Half4(v.x * l, v.y * l, v.z * l, v.w * l)
}
inline fun clamp(v: Half4, min: Half, max: Half): Half4 {
return Half4(
clamp(v.x, min, max),
clamp(v.y, min, max),
clamp(v.z, min, max),
clamp(v.w, min, max)
)
}
inline fun clamp(v: Half4, min: Half4, max: Half4): Half4 {
return Half4(
clamp(v.x, min.x, max.x),
clamp(v.y, min.y, max.y),
clamp(v.z, min.z, max.z),
clamp(v.w, min.z, max.w)
)
}
inline fun mix(a: Half4, b: Half4, x: Half): Half4 {
return Half4(
mix(a.x, b.x, x),
mix(a.y, b.y, x),
mix(a.z, b.z, x),
mix(a.w, b.w, x)
)
}
inline fun mix(a: Half4, b: Half4, x: Half4): Half4 {
return Half4(
mix(a.x, b.x, x.x),
mix(a.y, b.y, x.y),
mix(a.z, b.z, x.z),
mix(a.w, b.w, x.w))
}
inline fun min(v: Half4) = min(v.x, min(v.y, min(v.z, v.w)))
inline fun min(a: Half4, b: Half4): Half4 {
return Half4(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z), min(a.w, b.w))
}
inline fun max(v: Half4) = max(v.x, max(v.y, max(v.z, v.w)))
inline fun max(a: Half4, b: Half4): Half4 {
return Half4(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z), max(a.w, b.w))
}
inline fun transform(v: Half4, block: (Half) -> Half) = v.copy().transform(block)
inline fun lessThan(a: Half4, b: Half) = Bool4(a.x < b, a.y < b, a.z < b, a.w < b)
inline fun lessThan(a: Half4, b: Half4) = Bool4(a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w)
inline fun lessThanEqual(a: Half4, b: Half) = Bool4(a.x <= b, a.y <= b, a.z <= b, a.w <= b)
inline fun lessThanEqual(a: Half4, b: Half4) = Bool4(a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w)
inline fun greaterThan(a: Half4, b: Half) = Bool4(a.x > b, a.y > b, a.z > b, a.w > b)
inline fun greaterThan(a: Half4, b: Half4) = Bool4(a.x > b.y, a.y > b.y, a.z > b.z, a.w > b.w)
inline fun greaterThanEqual(a: Half4, b: Half) = Bool4(a.x >= b, a.y >= b, a.z >= b, a.w >= b)
inline fun greaterThanEqual(a: Half4, b: Half4) = Bool4(a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w)
inline fun equal(a: Half4, b: Half) = Bool4(a.x == b, a.y == b, a.z == b, a.w == b)
inline fun equal(a: Half4, b: Half4) = Bool4(a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w)
inline fun notEqual(a: Half4, b: Half) = Bool4(a.x != b, a.y != b, a.z != b, a.w != b)
inline fun notEqual(a: Half4, b: Half4) = Bool4(a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w)
inline infix fun Half4.lt(b: Half) = Bool4(x < b, y < b, z < b, a < b)
inline infix fun Half4.lt(b: Half4) = Bool4(x < b.x, y < b.y, z < b.z, w < b.w)
inline infix fun Half4.lte(b: Half) = Bool4(x <= b, y <= b, z <= b, w <= b)
inline infix fun Half4.lte(b: Half4) = Bool4(x <= b.x, y <= b.y, z <= b.z, w <= b.w)
inline infix fun Half4.gt(b: Half) = Bool4(x > b, y > b, z > b, w > b)
inline infix fun Half4.gt(b: Half4) = Bool4(x > b.x, y > b.y, z > b.z, w > b.w)
inline infix fun Half4.gte(b: Half) = Bool4(x >= b, y >= b, z >= b, w >= b)
inline infix fun Half4.gte(b: Half4) = Bool4(x >= b.x, y >= b.y, z >= b.z, w >= b.w)
inline infix fun Half4.eq(b: Half) = Bool4(x == b, y == b, z == b, w == b)
inline infix fun Half4.eq(b: Half4) = Bool4(x == b.x, y == b.y, z == b.z, w == b.w)
inline infix fun Half4.neq(b: Half) = Bool4(x != b, y != b, z != b, w != b)
inline infix fun Half4.neq(b: Half4) = Bool4(x != b.x, y != b.y, z != b.z, w != b.w)
+7
View File
@@ -16,6 +16,13 @@ android {
excludes += ['lib/*/libfilament-jni.so'] excludes += ['lib/*/libfilament-jni.so']
} }
} }
publishing {
singleVariant("fullRelease") {
withSourcesJar()
withJavadocJar()
}
}
} }
dependencies { dependencies {
+4 -1
View File
@@ -1,5 +1,5 @@
GROUP=com.google.android.filament GROUP=com.google.android.filament
VERSION_NAME=1.32.2 VERSION_NAME=1.42.0
POM_DESCRIPTION=Real-time physically based rendering engine for Android. POM_DESCRIPTION=Real-time physically based rendering engine for Android.
@@ -18,6 +18,9 @@ POM_DEVELOPER_NAME=Filament Team
org.gradle.jvmargs=-Xmx1536m org.gradle.jvmargs=-Xmx1536m
android.useAndroidX=true android.useAndroidX=true
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false
com.google.android.filament.tools-dir=../../../out/release/filament com.google.android.filament.tools-dir=../../../out/release/filament
com.google.android.filament.dist-dir=../out/android-release/filament com.google.android.filament.dist-dir=../out/android-release/filament
-53
View File
@@ -86,63 +86,10 @@ afterEvaluate { project ->
} }
} }
if (project.getPlugins().hasPlugin('com.android.application') ||
project.getPlugins().hasPlugin('com.android.library')) {
task androidJavadocs(type: Javadoc) {
source = android.sourceSets.main.java.source
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
excludes = ['**/*.kt']
}
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
classifier = 'javadoc'
from androidJavadocs.destinationDir
}
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.source
}
}
if (JavaVersion.current().isJava8Compatible()) {
allprojects {
tasks.withType(Javadoc) {
options.addStringOption('Xdoclint:none', '-quiet')
}
}
}
if (JavaVersion.current().isJava9Compatible()) {
allprojects {
tasks.withType(Javadoc) {
options.addBooleanOption('html5', true)
}
}
}
artifacts {
if (project.getPlugins().hasPlugin('com.android.application') ||
project.getPlugins().hasPlugin('com.android.library')) {
archives androidSourcesJar
archives androidJavadocsJar
}
}
android.libraryVariants.all { variant ->
tasks.androidJavadocs.doFirst {
classpath += files(variant.javaCompileProvider.get().classpath.files.join(File.pathSeparator))
}
}
publishing.publications.all { publication -> publishing.publications.all { publication ->
publication.groupId = GROUP publication.groupId = GROUP
publication.version = VERSION_NAME publication.version = VERSION_NAME
publication.artifact androidSourcesJar
publication.artifact androidJavadocsJar
configurePom(publication.pom) configurePom(publication.pom)
} }
+1 -1
View File
@@ -1,6 +1,6 @@
#Wed Nov 17 10:40:18 PST 2021 #Wed Nov 17 10:40:18 PST 2021
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
@@ -40,6 +40,11 @@ android {
dependenciesInfo { dependenciesInfo {
includeInApk = false includeInApk = false
} }
compileOptions {
sourceCompatibility versions.jdk
targetCompatibility versions.jdk
}
} }
dependencies { dependencies {
@@ -28,6 +28,7 @@ import com.google.android.filament.Fence
import com.google.android.filament.IndirectLight import com.google.android.filament.IndirectLight
import com.google.android.filament.Skybox import com.google.android.filament.Skybox
import com.google.android.filament.View import com.google.android.filament.View
import com.google.android.filament.View.OnPickCallback
import com.google.android.filament.utils.* import com.google.android.filament.utils.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -56,7 +57,9 @@ class MainActivity : Activity() {
private lateinit var modelViewer: ModelViewer private lateinit var modelViewer: ModelViewer
private lateinit var titlebarHint: TextView private lateinit var titlebarHint: TextView
private val doubleTapListener = DoubleTapListener() private val doubleTapListener = DoubleTapListener()
private val singleTapListener = SingleTapListener()
private lateinit var doubleTapDetector: GestureDetector private lateinit var doubleTapDetector: GestureDetector
private lateinit var singleTapDetector: GestureDetector
private var remoteServer: RemoteServer? = null private var remoteServer: RemoteServer? = null
private var statusToast: Toast? = null private var statusToast: Toast? = null
private var statusText: String? = null private var statusText: String? = null
@@ -77,6 +80,7 @@ class MainActivity : Activity() {
choreographer = Choreographer.getInstance() choreographer = Choreographer.getInstance()
doubleTapDetector = GestureDetector(applicationContext, doubleTapListener) doubleTapDetector = GestureDetector(applicationContext, doubleTapListener)
singleTapDetector = GestureDetector(applicationContext, singleTapListener)
modelViewer = ModelViewer(surfaceView) modelViewer = ModelViewer(surfaceView)
viewerContent.view = modelViewer.view viewerContent.view = modelViewer.view
@@ -88,6 +92,7 @@ class MainActivity : Activity() {
surfaceView.setOnTouchListener { _, event -> surfaceView.setOnTouchListener { _, event ->
modelViewer.onTouchEvent(event) modelViewer.onTouchEvent(event)
doubleTapDetector.onTouchEvent(event) doubleTapDetector.onTouchEvent(event)
singleTapDetector.onTouchEvent(event)
true true
} }
@@ -229,6 +234,7 @@ class MainActivity : Activity() {
modelViewer.scene.skybox = sky modelViewer.scene.skybox = sky
modelViewer.scene.indirectLight = ibl modelViewer.scene.indirectLight = ibl
viewerContent.indirectLight = ibl viewerContent.indirectLight = ibl
} }
} }
} }
@@ -337,6 +343,11 @@ class MainActivity : Activity() {
remoteServer?.close() remoteServer?.close()
} }
override fun onBackPressed() {
super.onBackPressed()
finish()
}
fun loadModelData(message: RemoteServer.ReceivedMessage) { fun loadModelData(message: RemoteServer.ReceivedMessage) {
Log.i(TAG, "Downloaded model ${message.label} (${message.buffer.capacity()} bytes)") Log.i(TAG, "Downloaded model ${message.label} (${message.buffer.capacity()} bytes)")
clearStatusText() clearStatusText()
@@ -425,4 +436,19 @@ class MainActivity : Activity() {
return super.onDoubleTap(e) return super.onDoubleTap(e)
} }
} }
// Just for testing purposes
inner class SingleTapListener : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapUp(event: MotionEvent): Boolean {
modelViewer.view.pick(
event.x.toInt(),
surfaceView.height - event.y.toInt(),
surfaceView.handler, {
val name = modelViewer.asset!!.getName(it.renderable)
Log.v("Filament", "Picked ${it.renderable}: " + name)
},
)
return super.onSingleTapUp(event)
}
}
} }
@@ -6,6 +6,10 @@ plugins {
project.ext.isSample = true project.ext.isSample = true
kotlin {
jvmToolchain(versions.jdk)
}
filamentTools { filamentTools {
materialInputDir = project.layout.projectDirectory.dir("src/main/materials") materialInputDir = project.layout.projectDirectory.dir("src/main/materials")
materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials") materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials")
@@ -36,6 +40,11 @@ android {
aaptOptions { aaptOptions {
noCompress 'filamat', 'ktx' noCompress 'filamat', 'ktx'
} }
compileOptions {
sourceCompatibility versions.jdk
targetCompatibility versions.jdk
}
} }
dependencies { dependencies {
@@ -30,6 +30,7 @@ import com.google.android.filament.*
import com.google.android.filament.RenderableManager.* import com.google.android.filament.RenderableManager.*
import com.google.android.filament.VertexBuffer.* import com.google.android.filament.VertexBuffer.*
import com.google.android.filament.android.DisplayHelper import com.google.android.filament.android.DisplayHelper
import com.google.android.filament.android.FilamentHelper
import com.google.android.filament.android.UiHelper import com.google.android.filament.android.UiHelper
import java.nio.ByteBuffer import java.nio.ByteBuffer
@@ -401,6 +402,8 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL) camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL)
view.viewport = Viewport(0, 0, width, height) view.viewport = Viewport(0, 0, width, height)
FilamentHelper.synchronizePendingFrames(engine)
} }
} }
@@ -6,6 +6,10 @@ plugins {
project.ext.isSample = true project.ext.isSample = true
kotlin {
jvmToolchain(versions.jdk)
}
filamentTools { filamentTools {
materialInputDir = project.layout.projectDirectory.dir("src/main/materials") materialInputDir = project.layout.projectDirectory.dir("src/main/materials")
materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials") materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials")
@@ -36,6 +40,11 @@ android {
aaptOptions { aaptOptions {
noCompress 'filamat', 'ktx' noCompress 'filamat', 'ktx'
} }
compileOptions {
sourceCompatibility versions.jdk
targetCompatibility versions.jdk
}
} }
dependencies { dependencies {
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
@@ -29,6 +29,7 @@ import com.google.android.filament.RenderableManager.PrimitiveType
import com.google.android.filament.VertexBuffer.AttributeType import com.google.android.filament.VertexBuffer.AttributeType
import com.google.android.filament.VertexBuffer.VertexAttribute import com.google.android.filament.VertexBuffer.VertexAttribute
import com.google.android.filament.android.DisplayHelper import com.google.android.filament.android.DisplayHelper
import com.google.android.filament.android.FilamentHelper
import com.google.android.filament.android.UiHelper import com.google.android.filament.android.UiHelper
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.ByteOrder import java.nio.ByteOrder
@@ -119,8 +120,13 @@ class MainActivity : Activity() {
private fun setupView() { private fun setupView() {
scene.skybox = Skybox.Builder().color(0.035f, 0.035f, 0.035f, 1.0f).build(engine) scene.skybox = Skybox.Builder().color(0.035f, 0.035f, 0.035f, 1.0f).build(engine)
// NOTE: Try to disable post-processing (tone-mapping, etc.) to see the difference if (engine.activeFeatureLevel == Engine.FeatureLevel.FEATURE_LEVEL_0) {
// view.isPostProcessingEnabled = false // post-processing is not supported at feature level 0
view.isPostProcessingEnabled = false
} else {
// NOTE: Try to disable post-processing (tone-mapping, etc.) to see the difference
// view.isPostProcessingEnabled = false
}
// Tell the view which camera we want to use // Tell the view which camera we want to use
view.camera = camera view.camera = camera
@@ -154,7 +160,11 @@ class MainActivity : Activity() {
} }
private fun loadMaterial() { private fun loadMaterial() {
readUncompressedAsset("materials/baked_color.filamat").let { var name = "materials/baked_color.filamat"
if (engine.activeFeatureLevel == Engine.FeatureLevel.FEATURE_LEVEL_0) {
name = "materials/baked_color_es2.filamat"
}
readUncompressedAsset(name).let {
material = Material.Builder().payload(it, it.remaining()).build(engine) material = Material.Builder().payload(it, it.remaining()).build(engine)
} }
} }
@@ -304,7 +314,17 @@ class MainActivity : Activity() {
inner class SurfaceCallback : UiHelper.RendererCallback { inner class SurfaceCallback : UiHelper.RendererCallback {
override fun onNativeWindowChanged(surface: Surface) { override fun onNativeWindowChanged(surface: Surface) {
swapChain?.let { engine.destroySwapChain(it) } swapChain?.let { engine.destroySwapChain(it) }
swapChain = engine.createSwapChain(surface, uiHelper.swapChainFlags)
// at feature level 0, we don't have post-processing, so we need to set
// the colorspace to sRGB (FIXME: it's not supported everywhere!)
var flags = uiHelper.swapChainFlags
if (engine.activeFeatureLevel == Engine.FeatureLevel.FEATURE_LEVEL_0) {
if (SwapChain.isSRGBSwapChainSupported(engine)) {
flags = flags or SwapChain.CONFIG_SRGB_COLORSPACE
}
}
swapChain = engine.createSwapChain(surface, flags)
displayHelper.attach(renderer, surfaceView.display); displayHelper.attach(renderer, surfaceView.display);
} }
@@ -327,6 +347,8 @@ class MainActivity : Activity() {
-aspect * zoom, aspect * zoom, -zoom, zoom, 0.0, 10.0) -aspect * zoom, aspect * zoom, -zoom, zoom, 0.0, 10.0)
view.viewport = Viewport(0, 0, width, height) view.viewport = Viewport(0, 0, width, height)
FilamentHelper.synchronizePendingFrames(engine)
} }
} }
@@ -17,7 +17,7 @@ material {
], ],
// This material disables all lighting // This material disables all lighting
shadingModel : unlit, shadingModel : unlit
} }
fragment { fragment {
@@ -0,0 +1,33 @@
// Simple unlit material that uses the colors associated with each vertex.
//
// This source material must be compiled to a binary material using the matc tool.
// The command used to compile this material is:
// matc -p mobile -a opengl -o app/src/main/assets/baked_color.filamat app/src/materials/baked_color.mat
//
// See build.gradle for an example of how to compile materials automatically
// Please refer to the documentation for more information about matc and the materials system.
material {
name : baked_color,
// Lists the required vertex attributes
// Here we only need a color (RGBA)
requires : [
color
],
// This material disables all lighting
shadingModel : unlit,
featureLevel : 0
}
fragment {
void material(inout MaterialInputs material) {
// You must always call the prepareMaterial() function
prepareMaterial(material);
// We set the material's color to the color interpolated from
// the model's vertices
material.baseColor = getColor();
}
}
@@ -6,6 +6,10 @@ plugins {
project.ext.isSample = true project.ext.isSample = true
kotlin {
jvmToolchain(versions.jdk)
}
filamentTools { filamentTools {
materialInputDir = project.layout.projectDirectory.dir("src/main/materials") materialInputDir = project.layout.projectDirectory.dir("src/main/materials")
materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials") materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials")
@@ -42,6 +46,11 @@ android {
aaptOptions { aaptOptions {
noCompress 'filamat', 'ktx' noCompress 'filamat', 'ktx'
} }
compileOptions {
sourceCompatibility versions.jdk
targetCompatibility versions.jdk
}
} }
dependencies { dependencies {
@@ -26,6 +26,7 @@ import android.view.animation.LinearInterpolator
import com.google.android.filament.* import com.google.android.filament.*
import com.google.android.filament.android.DisplayHelper import com.google.android.filament.android.DisplayHelper
import com.google.android.filament.android.FilamentHelper
import com.google.android.filament.android.UiHelper import com.google.android.filament.android.UiHelper
import java.nio.ByteBuffer import java.nio.ByteBuffer
@@ -117,9 +118,10 @@ class MainActivity : Activity() {
} }
private fun setupView() { private fun setupView() {
val ssaoOptions = view.ambientOcclusionOptions // ambient occlusion is the cheapest effect that adds a lot of quality
ssaoOptions.enabled = true view.ambientOcclusionOptions = view.ambientOcclusionOptions.apply {
view.ambientOcclusionOptions = ssaoOptions enabled = true
}
// NOTE: Try to disable post-processing (tone-mapping, etc.) to see the difference // NOTE: Try to disable post-processing (tone-mapping, etc.) to see the difference
// view.isPostProcessingEnabled = false // view.isPostProcessingEnabled = false
@@ -303,6 +305,8 @@ class MainActivity : Activity() {
camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL) camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL)
view.viewport = Viewport(0, 0, width, height) view.viewport = Viewport(0, 0, width, height)
FilamentHelper.synchronizePendingFrames(engine)
} }
} }
@@ -6,6 +6,10 @@ plugins {
project.ext.isSample = true project.ext.isSample = true
kotlin {
jvmToolchain(versions.jdk)
}
filamentTools { filamentTools {
materialInputDir = project.layout.projectDirectory.dir("src/main/materials") materialInputDir = project.layout.projectDirectory.dir("src/main/materials")
materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials") materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials")
@@ -35,6 +39,11 @@ android {
aaptOptions { aaptOptions {
noCompress 'filamat', 'ktx' noCompress 'filamat', 'ktx'
} }
compileOptions {
sourceCompatibility versions.jdk
targetCompatibility versions.jdk
}
} }
dependencies { dependencies {
@@ -29,6 +29,7 @@ import com.google.android.filament.*
import com.google.android.filament.RenderableManager.* import com.google.android.filament.RenderableManager.*
import com.google.android.filament.VertexBuffer.* import com.google.android.filament.VertexBuffer.*
import com.google.android.filament.android.DisplayHelper import com.google.android.filament.android.DisplayHelper
import com.google.android.filament.android.FilamentHelper
import com.google.android.filament.android.UiHelper import com.google.android.filament.android.UiHelper
import java.nio.ByteBuffer import java.nio.ByteBuffer
@@ -413,6 +414,8 @@ class MainActivity : Activity() {
camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL) camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL)
view.viewport = Viewport(0, 0, width, height) view.viewport = Viewport(0, 0, width, height)
FilamentHelper.synchronizePendingFrames(engine)
} }
} }
@@ -3,6 +3,10 @@ apply plugin: 'kotlin-android'
project.ext.isSample = true project.ext.isSample = true
kotlin {
jvmToolchain(versions.jdk)
}
android { android {
namespace 'com.google.android.filament.livewallpaper' namespace 'com.google.android.filament.livewallpaper'
@@ -18,6 +22,11 @@ android {
dependenciesInfo { dependenciesInfo {
includeInApk = false includeInApk = false
} }
compileOptions {
sourceCompatibility versions.jdk
targetCompatibility versions.jdk
}
} }
dependencies { dependencies {
@@ -31,6 +31,7 @@ import android.view.animation.LinearInterpolator
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import com.google.android.filament.* import com.google.android.filament.*
import com.google.android.filament.android.DisplayHelper import com.google.android.filament.android.DisplayHelper
import com.google.android.filament.android.FilamentHelper
import com.google.android.filament.android.UiHelper import com.google.android.filament.android.UiHelper
class FilamentLiveWallpaper : WallpaperService() { class FilamentLiveWallpaper : WallpaperService() {
@@ -226,6 +227,8 @@ class FilamentLiveWallpaper : WallpaperService() {
camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL) camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL)
view.viewport = Viewport(0, 0, width, height) view.viewport = Viewport(0, 0, width, height)
FilamentHelper.synchronizePendingFrames(engine)
} }
} }
} }
@@ -6,6 +6,10 @@ plugins {
project.ext.isSample = true project.ext.isSample = true
kotlin {
jvmToolchain(versions.jdk)
}
filamentTools { filamentTools {
meshInputFile = project.layout.projectDirectory.file("../../../third_party/models/shader_ball/shader_ball.obj") meshInputFile = project.layout.projectDirectory.file("../../../third_party/models/shader_ball/shader_ball.obj")
meshOutputDir = project.layout.projectDirectory.dir("src/main/assets/models") meshOutputDir = project.layout.projectDirectory.dir("src/main/assets/models")
@@ -46,6 +50,11 @@ android {
aaptOptions { aaptOptions {
noCompress 'filamat' noCompress 'filamat'
} }
compileOptions {
sourceCompatibility versions.jdk
targetCompatibility versions.jdk
}
} }
dependencies { dependencies {
@@ -26,6 +26,7 @@ import android.view.animation.LinearInterpolator
import com.google.android.filament.* import com.google.android.filament.*
import com.google.android.filament.android.DisplayHelper import com.google.android.filament.android.DisplayHelper
import com.google.android.filament.android.FilamentHelper
import com.google.android.filament.android.UiHelper import com.google.android.filament.android.UiHelper
import com.google.android.filament.filamat.MaterialBuilder import com.google.android.filament.filamat.MaterialBuilder
@@ -343,6 +344,8 @@ class MainActivity : Activity() {
camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL) camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL)
view.viewport = Viewport(0, 0, width, height) view.viewport = Viewport(0, 0, width, height)
FilamentHelper.synchronizePendingFrames(engine)
} }
} }
} }
@@ -6,6 +6,10 @@ plugins {
project.ext.isSample = true project.ext.isSample = true
kotlin {
jvmToolchain(versions.jdk)
}
filamentTools { filamentTools {
materialInputDir = project.layout.projectDirectory.dir("src/main/materials") materialInputDir = project.layout.projectDirectory.dir("src/main/materials")
materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials") materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials")
@@ -35,6 +39,11 @@ android {
aaptOptions { aaptOptions {
noCompress 'filamat', 'ktx' noCompress 'filamat', 'ktx'
} }
compileOptions {
sourceCompatibility versions.jdk
targetCompatibility versions.jdk
}
} }
dependencies { dependencies {
@@ -30,6 +30,7 @@ import com.google.android.filament.RenderableManager.*
import com.google.android.filament.Renderer.ClearOptions import com.google.android.filament.Renderer.ClearOptions
import com.google.android.filament.VertexBuffer.* import com.google.android.filament.VertexBuffer.*
import com.google.android.filament.android.DisplayHelper import com.google.android.filament.android.DisplayHelper
import com.google.android.filament.android.FilamentHelper
import com.google.android.filament.android.UiHelper import com.google.android.filament.android.UiHelper
import java.nio.ByteBuffer import java.nio.ByteBuffer
@@ -458,6 +459,8 @@ class MainActivity : Activity() {
view1.viewport = Viewport(width / 2, 0, width / 2, height / 2) view1.viewport = Viewport(width / 2, 0, width / 2, height / 2)
view2.viewport = Viewport(0, height / 2, width / 2, height / 2) view2.viewport = Viewport(0, height / 2, width / 2, height / 2)
view4.viewport = Viewport(width / 4, height / 4, width / 2, height / 2) view4.viewport = Viewport(width / 4, height / 4, width / 2, height / 2)
FilamentHelper.synchronizePendingFrames(engine)
} }
} }
@@ -6,6 +6,10 @@ plugins {
project.ext.isSample = true project.ext.isSample = true
kotlin {
jvmToolchain(versions.jdk)
}
filamentTools { filamentTools {
iblInputFile = project.layout.projectDirectory.file("../../../third_party/environments/studio_small_02_2k.hdr") iblInputFile = project.layout.projectDirectory.file("../../../third_party/environments/studio_small_02_2k.hdr")
iblOutputDir = project.layout.projectDirectory.dir("src/main/assets/envs") iblOutputDir = project.layout.projectDirectory.dir("src/main/assets/envs")
@@ -38,6 +42,11 @@ android {
aaptOptions { aaptOptions {
noCompress 'filamat' noCompress 'filamat'
} }
compileOptions {
sourceCompatibility versions.jdk
targetCompatibility versions.jdk
}
} }
dependencies { dependencies {
@@ -37,6 +37,7 @@ import com.google.android.filament.Camera;
import com.google.android.filament.Engine; import com.google.android.filament.Engine;
import com.google.android.filament.Entity; import com.google.android.filament.Entity;
import com.google.android.filament.EntityManager; import com.google.android.filament.EntityManager;
import com.google.android.filament.Fence;
import com.google.android.filament.Filament; import com.google.android.filament.Filament;
import com.google.android.filament.IndirectLight; import com.google.android.filament.IndirectLight;
import com.google.android.filament.LightManager; import com.google.android.filament.LightManager;
@@ -49,6 +50,7 @@ import com.google.android.filament.TransformManager;
import com.google.android.filament.Viewport; import com.google.android.filament.Viewport;
import com.google.android.filament.android.DisplayHelper; import com.google.android.filament.android.DisplayHelper;
import com.google.android.filament.android.FilamentHelper;
import com.google.android.filament.android.TextureHelper; import com.google.android.filament.android.TextureHelper;
import com.google.android.filament.android.UiHelper; import com.google.android.filament.android.UiHelper;
@@ -107,6 +109,7 @@ public class MainActivity extends Activity
mCamera.setProjection(60.0, aspect, 1.0, 2000.0, Camera.Fov.HORIZONTAL); mCamera.setProjection(60.0, aspect, 1.0, 2000.0, Camera.Fov.HORIZONTAL);
} }
mView.setViewport(new Viewport(0, 0, width, height)); mView.setViewport(new Viewport(0, 0, width, height));
FilamentHelper.synchronizePendingFrames(mEngine);
} }
@Override @Override
@@ -6,6 +6,10 @@ plugins {
project.ext.isSample = true project.ext.isSample = true
kotlin {
jvmToolchain(versions.jdk)
}
filamentTools { filamentTools {
materialInputDir = project.layout.projectDirectory.dir("src/main/materials") materialInputDir = project.layout.projectDirectory.dir("src/main/materials")
materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials") materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials")
@@ -36,6 +40,11 @@ android {
aaptOptions { aaptOptions {
noCompress 'filamat', 'ktx' noCompress 'filamat', 'ktx'
} }
compileOptions {
sourceCompatibility versions.jdk
targetCompatibility versions.jdk
}
} }
dependencies { dependencies {
@@ -38,6 +38,7 @@ import android.os.Build
import android.view.MotionEvent import android.view.MotionEvent
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import com.google.android.filament.android.DisplayHelper import com.google.android.filament.android.DisplayHelper
import com.google.android.filament.android.FilamentHelper
class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallback { class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallback {
@@ -401,6 +402,8 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL) camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL)
view.viewport = Viewport(0, 0, width, height) view.viewport = Viewport(0, 0, width, height)
FilamentHelper.synchronizePendingFrames(engine)
} }
} }
@@ -6,6 +6,10 @@ plugins {
project.ext.isSample = true project.ext.isSample = true
kotlin {
jvmToolchain(versions.jdk)
}
filamentTools { filamentTools {
materialInputDir = project.layout.projectDirectory.dir("src/main/materials") materialInputDir = project.layout.projectDirectory.dir("src/main/materials")
materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials") materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials")
@@ -36,6 +40,11 @@ android {
aaptOptions { aaptOptions {
noCompress 'filamat', 'ktx' noCompress 'filamat', 'ktx'
} }
compileOptions {
sourceCompatibility versions.jdk
targetCompatibility versions.jdk
}
} }
dependencies { dependencies {
@@ -29,6 +29,7 @@ import com.google.android.filament.RenderableManager.PrimitiveType
import com.google.android.filament.VertexBuffer.AttributeType import com.google.android.filament.VertexBuffer.AttributeType
import com.google.android.filament.VertexBuffer.VertexAttribute import com.google.android.filament.VertexBuffer.VertexAttribute
import com.google.android.filament.android.DisplayHelper import com.google.android.filament.android.DisplayHelper
import com.google.android.filament.android.FilamentHelper
import com.google.android.filament.android.UiHelper import com.google.android.filament.android.UiHelper
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.ByteOrder import java.nio.ByteOrder
@@ -327,6 +328,8 @@ class MainActivity : Activity() {
-aspect * zoom, aspect * zoom, -zoom, zoom, 0.0, 10.0) -aspect * zoom, aspect * zoom, -zoom, zoom, 0.0, 10.0)
view.viewport = Viewport(0, 0, width, height) view.viewport = Viewport(0, 0, width, height)
FilamentHelper.synchronizePendingFrames(engine)
} }
} }
@@ -6,6 +6,10 @@ plugins {
project.ext.isSample = true project.ext.isSample = true
kotlin {
jvmToolchain(versions.jdk)
}
filamentTools { filamentTools {
materialInputDir = project.layout.projectDirectory.dir("src/main/materials") materialInputDir = project.layout.projectDirectory.dir("src/main/materials")
materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials") materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials")
@@ -43,6 +47,11 @@ android {
aaptOptions { aaptOptions {
noCompress 'filamat', 'ktx' noCompress 'filamat', 'ktx'
} }
compileOptions {
sourceCompatibility versions.jdk
targetCompatibility versions.jdk
}
} }
dependencies { dependencies {
@@ -26,6 +26,7 @@ import android.view.animation.LinearInterpolator
import com.google.android.filament.* import com.google.android.filament.*
import com.google.android.filament.android.DisplayHelper import com.google.android.filament.android.DisplayHelper
import com.google.android.filament.android.FilamentHelper
import com.google.android.filament.utils.* import com.google.android.filament.utils.*
import com.google.android.filament.android.UiHelper import com.google.android.filament.android.UiHelper
@@ -230,7 +231,7 @@ class MainActivity : Activity() {
animator.repeatCount = ValueAnimator.INFINITE animator.repeatCount = ValueAnimator.INFINITE
animator.addUpdateListener { a -> animator.addUpdateListener { a ->
val v = (a.animatedValue as Float) val v = (a.animatedValue as Float)
camera.lookAt(cos(v) * 4.5, 1.5, sin(v) * 4.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) camera.lookAt(cos(v) * 5.5, 1.5, sin(v) * 5.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
} }
animator.start() animator.start()
} }
@@ -252,7 +253,7 @@ class MainActivity : Activity() {
// Stop the animation and any pending frame // Stop the animation and any pending frame
choreographer.removeFrameCallback(frameScheduler) choreographer.removeFrameCallback(frameScheduler)
animator.cancel(); animator.cancel()
// Always detach the surface before destroying the engine // Always detach the surface before destroying the engine
uiHelper.detach() uiHelper.detach()
@@ -323,6 +324,8 @@ class MainActivity : Activity() {
camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL) camera.setProjection(45.0, aspect, 0.1, 20.0, Camera.Fov.VERTICAL)
view.viewport = Viewport(0, 0, width, height) view.viewport = Viewport(0, 0, width, height)
FilamentHelper.synchronizePendingFrames(engine)
} }
} }
@@ -6,6 +6,10 @@ plugins {
project.ext.isSample = true project.ext.isSample = true
kotlin {
jvmToolchain(versions.jdk)
}
filamentTools { filamentTools {
materialInputDir = project.layout.projectDirectory.dir("src/main/materials") materialInputDir = project.layout.projectDirectory.dir("src/main/materials")
materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials") materialOutputDir = project.layout.projectDirectory.dir("src/main/assets/materials")
@@ -36,6 +40,11 @@ android {
aaptOptions { aaptOptions {
noCompress 'filamat', 'ktx' noCompress 'filamat', 'ktx'
} }
compileOptions {
sourceCompatibility versions.jdk
targetCompatibility versions.jdk
}
} }
dependencies { dependencies {
@@ -33,6 +33,7 @@ import com.google.android.filament.*
import com.google.android.filament.RenderableManager.* import com.google.android.filament.RenderableManager.*
import com.google.android.filament.VertexBuffer.* import com.google.android.filament.VertexBuffer.*
import com.google.android.filament.android.DisplayHelper import com.google.android.filament.android.DisplayHelper
import com.google.android.filament.android.FilamentHelper
import com.google.android.filament.android.UiHelper import com.google.android.filament.android.UiHelper
import java.nio.ByteBuffer import java.nio.ByteBuffer
@@ -139,9 +140,9 @@ class MainActivity : Activity() {
camera = engine.createCamera(engine.entityManager.create()) camera = engine.createCamera(engine.entityManager.create())
// clear the swapchain with transparent pixels // clear the swapchain with transparent pixels
val options = renderer.clearOptions renderer.clearOptions = renderer.clearOptions.apply {
options.clear = true clear = true
renderer.clearOptions = options }
} }
private fun setupView() { private fun setupView() {
@@ -350,6 +351,8 @@ class MainActivity : Activity() {
-aspect * zoom, aspect * zoom, -zoom, zoom, 0.0, 10.0) -aspect * zoom, aspect * zoom, -zoom, zoom, 0.0, 10.0)
view.viewport = Viewport(0, 0, width, height) view.viewport = Viewport(0, 0, width, height)
FilamentHelper.synchronizePendingFrames(engine)
} }
} }
+5 -3
View File
@@ -90,8 +90,8 @@ function print_help {
echo " Desktop matc target, release build:" echo " Desktop matc target, release build:"
echo " \$ ./$self_name release matc" echo " \$ ./$self_name release matc"
echo "" echo ""
echo " Build gltf_viewer then immediately run it with no arguments:" echo " Build gltf_viewer:"
echo " \$ ./$self_name release run_gltf_viewer" echo " \$ ./$self_name release gltf_viewer"
echo "" echo ""
} }
@@ -491,6 +491,7 @@ function build_android {
./gradlew \ ./gradlew \
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \ -Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \ -Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
${MATOPT_GRADLE_OPTION} \
:samples:${sample}:assembleDebug :samples:${sample}:assembleDebug
done done
fi fi
@@ -539,6 +540,7 @@ function build_android {
./gradlew \ ./gradlew \
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \ -Pcom.google.android.filament.dist-dir=../out/android-release/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \ -Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
${MATOPT_GRADLE_OPTION} \
:samples:${sample}:assembleRelease :samples:${sample}:assembleRelease
done done
fi fi
@@ -756,7 +758,7 @@ function run_tests {
pushd "$(dirname "$0")" > /dev/null pushd "$(dirname "$0")" > /dev/null
while getopts ":hacCfijmp:q:uvslwtedk:b" opt; do while getopts ":hacCfgijmp:q:uvslwtedk:b" opt; do
case ${opt} in case ${opt} in
h) h)
print_help print_help
+9 -2
View File
@@ -44,13 +44,20 @@ elif [[ "$LC_UNAME" == "darwin" ]]; then
fi fi
source `dirname $0`/../common/build-common.sh source `dirname $0`/../common/build-common.sh
if [[ "$GITHUB_WORKFLOW" ]]; then
java_version=$(java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1)
if [[ "$java_version" < 17 ]]; then
echo "Android builds require Java 17, found version ${java_version} instead"
exit 0
fi
fi
# Unless explicitly specified, NDK version will be set to match exactly the required one # 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)} FILAMENT_NDK_VERSION=${FILAMENT_NDK_VERSION:-$(cat `dirname $0`/ndk.version)}
# Install the required NDK version specifically (if not present) # Install the required NDK version specifically (if not present)
if [[ ! -d "${ANDROID_HOME}/ndk/$FILAMENT_NDK_VERSION" ]]; then if [[ ! -d "${ANDROID_HOME}/ndk/$FILAMENT_NDK_VERSION" ]]; then
# NOTE: We MUST use Java 1.8 to run sdkmanager currently, it fails starting with Java 11 ${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager "ndk;$FILAMENT_NDK_VERSION" > /dev/null
JAVA_HOME=${JAVA_HOME_8_X64} ${ANDROID_HOME}/tools/bin/sdkmanager "ndk;$FILAMENT_NDK_VERSION" > /dev/null
fi fi
# Only build 1 64 bit target during presubmit to cut down build times during presubmit # Only build 1 64 bit target during presubmit to cut down build times during presubmit
+10 -1
View File
@@ -2,6 +2,11 @@
set -e set -e
case "$(uname -s)" in
Darwin*) IS_DARWIN=1;;
*) ;;
esac
function print_help { function print_help {
local SELF_NAME local SELF_NAME
SELF_NAME=$(basename "$0") SELF_NAME=$(basename "$0")
@@ -45,7 +50,11 @@ function replace {
FIND_STR="${1//\{\{VERSION\}\}/${VERSION_REGEX}}" FIND_STR="${1//\{\{VERSION\}\}/${VERSION_REGEX}}"
REPLACE_STR="${1//\{\{VERSION\}\}/${NEW_VERSION}}" REPLACE_STR="${1//\{\{VERSION\}\}/${NEW_VERSION}}"
local FILE_NAME="$2" local FILE_NAME="$2"
sed -i '' -E "s/${FIND_STR}/${REPLACE_STR}/" "${FILE_NAME}" if [ IS_DARWIN ]; then
sed -i '' -E "s/${FIND_STR}/${REPLACE_STR}/" "${FILE_NAME}"
else
sed -i -E "s/${FIND_STR}/${REPLACE_STR}/" "${FILE_NAME}"
fi
} }
# The following are the canonical locations where the Filament version number is referenced. # The following are the canonical locations where the Filament version number is referenced.
-8
View File
@@ -3,12 +3,4 @@
if [[ "$GITHUB_WORKFLOW" ]]; then if [[ "$GITHUB_WORKFLOW" ]]; then
echo "Running workflow $GITHUB_WORKFLOW (event: $GITHUB_EVENT_NAME, action: $GITHUB_ACTION)" echo "Running workflow $GITHUB_WORKFLOW (event: $GITHUB_EVENT_NAME, action: $GITHUB_ACTION)"
CONTINUOUS_INTEGRATION=true CONTINUOUS_INTEGRATION=true
# Force Java to be Java 11 minimum, it defaults to 8 in GitHub runners for some platforms
export JAVA_HOME=${JAVA_HOME_11_X64}
java_version=$(java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1)
if [[ "$java_version" < 11 ]]; then
echo "Android builds require Java 11, found version ${java_version} instead"
exit 0
fi
fi fi
+5 -5
View File
File diff suppressed because one or more lines are too long
+6 -6
View File
@@ -200,7 +200,7 @@ Energy conservation is one of the key components of a good BRDF for physically b
## Specular BRDF ## Specular BRDF
For the specular term, $f_m$ is a mirror BRDF that can be modeled with the Fresnel law, noted $F$ in the Cook-Torrance approximation of the microfacet model integration: For the specular term, $f_r$ is a mirror BRDF that can be modeled with the Fresnel law, noted $F$ in the Cook-Torrance approximation of the microfacet model integration:
$$\begin{equation} $$\begin{equation}
f_r(v,l) = \frac{D(h, \alpha) G(v, l, \alpha) F(v, h, f0)}{4(\NoV)(\NoL)} f_r(v,l) = \frac{D(h, \alpha) G(v, l, \alpha) F(v, h, f0)}{4(\NoV)(\NoL)}
@@ -485,7 +485,7 @@ void BRDF(...) {
// perceptually linear roughness to roughness (see parameterization) // perceptually linear roughness to roughness (see parameterization)
float roughness = perceptualRoughness * perceptualRoughness; float roughness = perceptualRoughness * perceptualRoughness;
float D = D_GGX(NoH, a); float D = D_GGX(NoH, roughness);
vec3 F = F_Schlick(LoH, f0); vec3 F = F_Schlick(LoH, f0);
float V = V_SmithGGXCorrelated(NoV, NoL, roughness); float V = V_SmithGGXCorrelated(NoV, NoL, roughness);
@@ -2016,7 +2016,7 @@ I(f(n, v, \alpha)) \equiv \frac{1}{N}\sum_{\forall \, i \in image} f(l_i,
\end{equation}$$ \end{equation}$$
However, in practice we're using _importance sampling_ which needs to take the $pdf$ of the distribution However, in practice we're using _importance sampling_ which needs to take the $pdf$ of the distribution
into account and adds a term $\frac{\left<\VoH\right>}{D(h_i, \alpha)\left<\NoH\right>}$. into account and adds a term $\frac{4\left<\VoH\right>}{D(h_i, \alpha)\left<\NoH\right>}$.
See Importance Sampling For The IBL section: See Importance Sampling For The IBL section:
$$\begin{equation}\label{iblImportanceSampling} $$\begin{equation}\label{iblImportanceSampling}
@@ -3486,15 +3486,15 @@ The _important direction samples_ $l_i$ are calculated as the reflection of $v$
**do not** have the same PDF as $h_i$. The PDF of a transformed distribution is given by: **do not** have the same PDF as $h_i$. The PDF of a transformed distribution is given by:
$$\begin{equation} $$\begin{equation}
p(T_r(x)) = p(x) |J(T_r)| p(T_r(x)) = p(x) |J(T_r)|^{-1}
\end{equation}$$ \end{equation}$$
Where $|J(T_r)|$ is the determinant of the Jacobian of the transform. In our case we're considering Where $|J(T_r)|$ is the determinant of the Jacobian of the transform. In our case we're considering
the transform from $h_i$ to $l_i$ and the determinant of its Jacobian is given in \ref{iblPDF}. the transform from $h_i$ to $l_i$ and the determinant of its Jacobian is given in \ref{iblPDF}.
$$\begin{equation}\label{iblPDF} $$\begin{equation}\label{iblPDF}
p(l,v,\Theta) = D(h,\alpha) \left< \NoH \right> |J_{h \rightarrow l}| \\ p(l,v,\Theta) = D(h,\alpha) \left< \NoH \right> |J_{h \rightarrow l}|^{-1} \\
|J_{h \rightarrow l}| = \frac{1}{4 \left< \VoH \right>} |J_{h \rightarrow l}| = 4 \left< \VoH \right>
\end{equation}$$ \end{equation}$$
### Choosing important directions ### Choosing important directions
+124 -68
View File
File diff suppressed because one or more lines are too long
+91 -1
View File
@@ -1076,13 +1076,71 @@ fragment {
} }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### General: constants
Type
: array of constant objects
Value
: Each entry is an object with the properties `name` and `type`, both of `string` type. The name
must be a valid GLSL identifier. Entries also have an optional `default`, which can either be a
`bool` or `number`, depending on the `type` of the constant. The type must be one of the types
described in table [materialConstantsTypes].
Type | Description | Default
:----------------------|:-----------------------------------------|:------------------
int | A signed, 32 bit GLSL int | 0
float | A single-precision GLSL float | 0.0
bool | A GLSL bool | false
[Table [materialConstantsTypes]: Material constants types]
Description
: Lists the constant parameters accepted by your material. These constants can be set, or
"specialized", at runtime when loading a material package. Multiple materials can be loaded from
the same material package with differing constant parameter specializations. Once a material is
loaded from a material package, its constant parameters cannot be changed. Compared to regular
parameters, constant parameters allow the compiler to generate more efficient code. Access
constant parameters from the shader by prefixing the name with `materialConstant_`. For example,
a constant parameter named `myConstant` is accessed in the shader as
`materialConstant_myConstant`. If a constant parameter is not set at runtime, the default is
used.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
constants : [
{
name : overrideAlpha,
type : bool
},
{
name : customAlpha,
type : float,
default : 0.5
}
],
shadingModel : lit,
blending : transparent,
}
fragment {
void material(inout MaterialInputs material) {
prepareMaterial(material);
if (materialConstants_overrideAlpha) {
material.baseColor.a = materialConstants_customAlpha;
material.baseColor.rgb *= material.baseColor.a;
}
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### General: variantFilter ### General: variantFilter
Type Type
: array of `string` : array of `string`
Value Value
: Each entry must be any of `dynamicLighting`, `directionalLighting`, `shadowReceiver`,`skinning` or `ssr`. : Each entry must be any of `dynamicLighting`, `directionalLighting`, `shadowReceiver`,
`skinning`, `ssr`, or `stereo`.
Description Description
: Used to specify a list of shader variants that the application guarantees will never be : Used to specify a list of shader variants that the application guarantees will never be
@@ -1101,6 +1159,7 @@ Description of the variants:
- `fog`, used when global fog is applied to the scene - `fog`, used when global fog is applied to the scene
- `vsm`, used when VSM shadows are enabled and the object is a shadow receiver - `vsm`, used when VSM shadows are enabled and the object is a shadow receiver
- `ssr`, used when screen-space reflections are enabled in the View - `ssr`, used when screen-space reflections are enabled in the View
- `stereo`, used when stereoscopic rendering is enabled in the View
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material { material {
@@ -2315,6 +2374,15 @@ type aliases:
match the API-level world space. To obtain the position of the API-level camera, custom match the API-level world space. To obtain the position of the API-level camera, custom
materials can use `getUserWorldFromWorldMatrix()` to transform `getWorldCameraPosition()`. materials can use `getUserWorldFromWorldMatrix()` to transform `getWorldCameraPosition()`.
### Material globals
Name | Type | Description
:-----------------------------------|:--------:|:------------------------------------
**getMaterialGlobal0()** | float4 | A vec4 visible by all materials, its value is set by `View::setMaterialGlobal(0, float4)`. Its default value is {0,0,0,1}.
**getMaterialGlobal1()** | float4 | A vec4 visible by all materials, its value is set by `View::setMaterialGlobal(1, float4)`. Its default value is {0,0,0,1}.
**getMaterialGlobal2()** | float4 | A vec4 visible by all materials, its value is set by `View::setMaterialGlobal(2, float4)`. Its default value is {0,0,0,1}.
**getMaterialGlobal3()** | float4 | A vec4 visible by all materials, its value is set by `View::setMaterialGlobal(3, float4)`. Its default value is {0,0,0,1}.
### Vertex only ### Vertex only
The following APIs are only available from the vertex block: The following APIs are only available from the vertex block:
@@ -2527,4 +2595,26 @@ pre-multiplied ahead of time. On Android, any texture uploaded from a
[Bitmap](https://developer.android.com/reference/android/graphics/Bitmap.html) will be [Bitmap](https://developer.android.com/reference/android/graphics/Bitmap.html) will be
pre-multiplied by default. pre-multiplied by default.
# Sampler usage in Materials
The number of usable sampler parameters (e.g.: type is `sampler2d`) in materials is limited and
depends on the material properties, shading model, feature level and variant filter.
## Feature level 1 and 2
`unlit` materials can use up to 12 samplers by default.
`lit` materials can use up to 9 samplers by default, however if `refractionMode` or `reflectionMode`
is set to `screenspace` that number is reduced to 8.
Finally if `variantFilter` contains the `fog` filter, an extra sampler is made available, such that
`unlit` materials can use up to 13 and `lit` materials up to 10 samplers by default.
## Feature level 3
16 samplers are available.
!!! TIP: external samplers
Be aware that `external` samplers account for 2 regular samplers.
<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="../third_party/markdeep/markdeep.min.js"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script> <!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="../third_party/markdeep/markdeep.min.js"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script>
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+12 -3
View File
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+34 -62
View File
@@ -26,6 +26,7 @@ set(PUBLIC_HDRS
include/filament/Frustum.h include/filament/Frustum.h
include/filament/IndexBuffer.h include/filament/IndexBuffer.h
include/filament/IndirectLight.h include/filament/IndirectLight.h
include/filament/InstanceBuffer.h
include/filament/LightManager.h include/filament/LightManager.h
include/filament/Material.h include/filament/Material.h
include/filament/MaterialInstance.h include/filament/MaterialInstance.h
@@ -67,6 +68,7 @@ set(SRCS
src/HwRenderPrimitiveFactory.cpp src/HwRenderPrimitiveFactory.cpp
src/IndexBuffer.cpp src/IndexBuffer.cpp
src/IndirectLight.cpp src/IndirectLight.cpp
src/InstanceBuffer.cpp
src/LightManager.cpp src/LightManager.cpp
src/Material.cpp src/Material.cpp
src/MaterialInstance.cpp src/MaterialInstance.cpp
@@ -108,6 +110,7 @@ set(SRCS
src/details/Fence.cpp src/details/Fence.cpp
src/details/IndexBuffer.cpp src/details/IndexBuffer.cpp
src/details/IndirectLight.cpp src/details/IndirectLight.cpp
src/details/InstanceBuffer.cpp
src/details/Material.cpp src/details/Material.cpp
src/details/MaterialInstance.cpp src/details/MaterialInstance.cpp
src/details/MorphTargetBuffer.cpp src/details/MorphTargetBuffer.cpp
@@ -171,6 +174,7 @@ set(PRIVATE_HDRS
src/details/Fence.h src/details/Fence.h
src/details/IndexBuffer.h src/details/IndexBuffer.h
src/details/IndirectLight.h src/details/IndirectLight.h
src/details/InstanceBuffer.h
src/details/Material.h src/details/Material.h
src/details/MaterialInstance.h src/details/MaterialInstance.h
src/details/MorphTargetBuffer.h src/details/MorphTargetBuffer.h
@@ -212,6 +216,7 @@ set(MATERIAL_SRCS
src/materials/colorGrading/colorGrading.mat src/materials/colorGrading/colorGrading.mat
src/materials/colorGrading/colorGradingAsSubpass.mat src/materials/colorGrading/colorGradingAsSubpass.mat
src/materials/colorGrading/customResolveAsSubpass.mat src/materials/colorGrading/customResolveAsSubpass.mat
src/materials/debugShadowCascades.mat
src/materials/defaultMaterial.mat src/materials/defaultMaterial.mat
src/materials/dof/dof.mat src/materials/dof/dof.mat
src/materials/dof/dofCoc.mat src/materials/dof/dofCoc.mat
@@ -232,19 +237,17 @@ set(MATERIAL_SRCS
src/materials/skybox.mat src/materials/skybox.mat
src/materials/ssao/sao.mat src/materials/ssao/sao.mat
src/materials/ssao/saoBentNormals.mat src/materials/ssao/saoBentNormals.mat
src/materials/separableGaussianBlur1.mat src/materials/separableGaussianBlur.mat
src/materials/separableGaussianBlur2.mat
src/materials/separableGaussianBlur3.mat
src/materials/separableGaussianBlur4.mat
src/materials/separableGaussianBlur1L.mat
src/materials/separableGaussianBlur2L.mat
src/materials/separableGaussianBlur3L.mat
src/materials/separableGaussianBlur4L.mat
src/materials/antiAliasing/fxaa.mat src/materials/antiAliasing/fxaa.mat
src/materials/antiAliasing/taa.mat src/materials/antiAliasing/taa.mat
src/materials/vsmMipmap.mat src/materials/vsmMipmap.mat
) )
set(MATERIAL_ES2_SRCS
src/materials/defaultMaterial0.mat
src/materials/skybox0.mat
)
# Embed the binary resource blob for materials. # Embed the binary resource blob for materials.
get_resgen_vars(${RESOURCE_DIR} materials) get_resgen_vars(${RESOURCE_DIR} materials)
list(APPEND PRIVATE_HDRS ${RESGEN_HEADER}) list(APPEND PRIVATE_HDRS ${RESGEN_HEADER})
@@ -310,6 +313,23 @@ foreach (mat_src ${MATERIAL_SRCS})
list(APPEND MATERIAL_BINS ${output_path}) list(APPEND MATERIAL_BINS ${output_path})
endforeach() endforeach()
if (IS_MOBILE_TARGET AND FILAMENT_SUPPORTS_OPENGL)
foreach (mat_src ${MATERIAL_ES2_SRCS})
get_filename_component(localname "${mat_src}" NAME_WE)
get_filename_component(fullname "${mat_src}" ABSOLUTE)
set(output_path "${MATERIAL_DIR}/${localname}.filamat")
add_custom_command(
OUTPUT ${output_path}
COMMAND matc -a opengl -p ${MATC_TARGET} ${MATC_OPT_FLAGS} -o ${output_path} ${fullname}
MAIN_DEPENDENCY ${fullname}
DEPENDS matc
COMMENT "Compiling material ${mat_src} to ${output_path}"
)
list(APPEND MATERIAL_BINS ${output_path})
endforeach ()
endif ()
# Additional dependencies on included files for materials # Additional dependencies on included files for materials
add_custom_command( add_custom_command(
@@ -374,8 +394,8 @@ add_custom_command(
OUTPUT "${MATERIAL_DIR}/sao.filamat" OUTPUT "${MATERIAL_DIR}/sao.filamat"
DEPENDS src/materials/ssao/ssaoUtils.fs DEPENDS src/materials/ssao/ssaoUtils.fs
DEPENDS src/materials/ssao/ssct.fs DEPENDS src/materials/ssao/ssct.fs
DEPENDS src/materials/ssao/depthUtils.fs DEPENDS src/materials/utils/depthUtils.fs
DEPENDS src/materials/ssao/geometry.fs DEPENDS src/materials/utils/geometry.fs
DEPENDS src/materials/ssao/saoImpl.fs DEPENDS src/materials/ssao/saoImpl.fs
DEPENDS src/materials/ssao/ssctImpl.fs DEPENDS src/materials/ssao/ssctImpl.fs
APPEND APPEND
@@ -385,8 +405,8 @@ add_custom_command(
OUTPUT "${MATERIAL_DIR}/saoBentNormals.filamat" OUTPUT "${MATERIAL_DIR}/saoBentNormals.filamat"
DEPENDS src/materials/ssao/ssaoUtils.fs DEPENDS src/materials/ssao/ssaoUtils.fs
DEPENDS src/materials/ssao/ssct.fs DEPENDS src/materials/ssao/ssct.fs
DEPENDS src/materials/ssao/depthUtils.fs DEPENDS src/materials/utils/depthUtils.fs
DEPENDS src/materials/ssao/geometry.fs DEPENDS src/materials/utils/geometry.fs
DEPENDS src/materials/ssao/saoImpl.fs DEPENDS src/materials/ssao/saoImpl.fs
DEPENDS src/materials/ssao/ssctImpl.fs DEPENDS src/materials/ssao/ssctImpl.fs
APPEND APPEND
@@ -435,56 +455,7 @@ add_custom_command(
) )
add_custom_command( add_custom_command(
OUTPUT "${MATERIAL_DIR}/separableGaussianBlur1.filamat" OUTPUT "${MATERIAL_DIR}/separableGaussianBlur.filamat"
DEPENDS src/materials/separableGaussianBlur.vs
DEPENDS src/materials/separableGaussianBlur.fs
APPEND
)
add_custom_command(
OUTPUT "${MATERIAL_DIR}/separableGaussianBlur2.filamat"
DEPENDS src/materials/separableGaussianBlur.vs
DEPENDS src/materials/separableGaussianBlur.fs
APPEND
)
add_custom_command(
OUTPUT "${MATERIAL_DIR}/separableGaussianBlur3.filamat"
DEPENDS src/materials/separableGaussianBlur.vs
DEPENDS src/materials/separableGaussianBlur.fs
APPEND
)
add_custom_command(
OUTPUT "${MATERIAL_DIR}/separableGaussianBlur4.filamat"
DEPENDS src/materials/separableGaussianBlur.vs
DEPENDS src/materials/separableGaussianBlur.fs
APPEND
)
add_custom_command(
OUTPUT "${MATERIAL_DIR}/separableGaussianBlur1L.filamat"
DEPENDS src/materials/separableGaussianBlur.vs
DEPENDS src/materials/separableGaussianBlur.fs
APPEND
)
add_custom_command(
OUTPUT "${MATERIAL_DIR}/separableGaussianBlur2L.filamat"
DEPENDS src/materials/separableGaussianBlur.vs
DEPENDS src/materials/separableGaussianBlur.fs
APPEND
)
add_custom_command(
OUTPUT "${MATERIAL_DIR}/separableGaussianBlur3L.filamat"
DEPENDS src/materials/separableGaussianBlur.vs
DEPENDS src/materials/separableGaussianBlur.fs
APPEND
)
add_custom_command(
OUTPUT "${MATERIAL_DIR}/separableGaussianBlur4L.filamat"
DEPENDS src/materials/separableGaussianBlur.vs DEPENDS src/materials/separableGaussianBlur.vs
DEPENDS src/materials/separableGaussianBlur.fs DEPENDS src/materials/separableGaussianBlur.fs
APPEND APPEND
@@ -564,6 +535,7 @@ elseif(WEBGL)
else() else()
set(OPTIMIZATION_FLAGS set(OPTIMIZATION_FLAGS
-ffast-math -ffast-math
-fno-finite-math-only
-ffp-contract=fast -ffp-contract=fast
# TODO: aggressive vectorization is currently broken on Android # TODO: aggressive vectorization is currently broken on Android
# -fslp-vectorize-aggressive # -fslp-vectorize-aggressive
+25 -18
View File
@@ -25,11 +25,12 @@ set(PUBLIC_HDRS
set(SRCS set(SRCS
src/BackendUtils.cpp src/BackendUtils.cpp
src/BlobCacheKey.cpp
src/Callable.cpp src/Callable.cpp
src/CallbackHandler.cpp
src/CircularBuffer.cpp src/CircularBuffer.cpp
src/CommandBufferQueue.cpp src/CommandBufferQueue.cpp
src/CommandStream.cpp src/CommandStream.cpp
src/CompilerThreadPool.cpp
src/Driver.cpp src/Driver.cpp
src/Handle.cpp src/Handle.cpp
src/HandleAllocator.cpp src/HandleAllocator.cpp
@@ -54,6 +55,7 @@ set(PRIVATE_HDRS
include/private/backend/PlatformFactory.h include/private/backend/PlatformFactory.h
include/private/backend/SamplerGroup.h include/private/backend/SamplerGroup.h
src/CommandStreamDispatcher.h src/CommandStreamDispatcher.h
src/CompilerThreadPool.h
src/DataReshaper.h src/DataReshaper.h
src/DriverBase.h src/DriverBase.h
) )
@@ -65,10 +67,14 @@ set(PRIVATE_HDRS
if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMENT_USE_SWIFTSHADER) if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMENT_USE_SWIFTSHADER)
list(APPEND SRCS list(APPEND SRCS
include/backend/platforms/OpenGLPlatform.h include/backend/platforms/OpenGLPlatform.h
src/opengl/CallbackManager.h
src/opengl/CallbackManager.cpp
src/opengl/gl_headers.cpp src/opengl/gl_headers.cpp
src/opengl/gl_headers.h src/opengl/gl_headers.h
src/opengl/GLUtils.cpp src/opengl/GLUtils.cpp
src/opengl/GLUtils.h src/opengl/GLUtils.h
src/opengl/OpenGLBlobCache.cpp
src/opengl/OpenGLBlobCache.h
src/opengl/OpenGLContext.cpp src/opengl/OpenGLContext.cpp
src/opengl/OpenGLContext.h src/opengl/OpenGLContext.h
src/opengl/OpenGLDriver.cpp src/opengl/OpenGLDriver.cpp
@@ -79,6 +85,8 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMEN
src/opengl/OpenGLPlatform.cpp src/opengl/OpenGLPlatform.cpp
src/opengl/OpenGLTimerQuery.cpp src/opengl/OpenGLTimerQuery.cpp
src/opengl/OpenGLTimerQuery.h src/opengl/OpenGLTimerQuery.h
src/opengl/ShaderCompilerService.cpp
src/opengl/ShaderCompilerService.h
) )
if (EGL) if (EGL)
list(APPEND SRCS src/opengl/platforms/PlatformEGL.cpp) list(APPEND SRCS src/opengl/platforms/PlatformEGL.cpp)
@@ -96,6 +104,7 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMEN
list(APPEND SRCS src/opengl/platforms/CocoaTouchExternalImage.mm) list(APPEND SRCS src/opengl/platforms/CocoaTouchExternalImage.mm)
elseif (APPLE) elseif (APPLE)
list(APPEND SRCS src/opengl/platforms/PlatformCocoaGL.mm) list(APPEND SRCS src/opengl/platforms/PlatformCocoaGL.mm)
list(APPEND SRCS src/opengl/platforms/CocoaExternalImage.mm)
elseif (WEBGL) elseif (WEBGL)
list(APPEND SRCS src/opengl/platforms/PlatformWebGL.cpp) list(APPEND SRCS src/opengl/platforms/PlatformWebGL.cpp)
elseif (LINUX) elseif (LINUX)
@@ -156,6 +165,9 @@ endif()
if (FILAMENT_SUPPORTS_VULKAN) if (FILAMENT_SUPPORTS_VULKAN)
list(APPEND SRCS list(APPEND SRCS
include/backend/platforms/VulkanPlatform.h include/backend/platforms/VulkanPlatform.h
src/vulkan/platform/VulkanPlatform.cpp
src/vulkan/platform/VulkanPlatformSwapChainImpl.cpp
src/vulkan/platform/VulkanPlatformSwapChainImpl.h
src/vulkan/VulkanBlitter.cpp src/vulkan/VulkanBlitter.cpp
src/vulkan/VulkanBlitter.h src/vulkan/VulkanBlitter.h
src/vulkan/VulkanBuffer.cpp src/vulkan/VulkanBuffer.cpp
@@ -165,8 +177,6 @@ if (FILAMENT_SUPPORTS_VULKAN)
src/vulkan/VulkanConstants.h src/vulkan/VulkanConstants.h
src/vulkan/VulkanContext.cpp src/vulkan/VulkanContext.cpp
src/vulkan/VulkanContext.h src/vulkan/VulkanContext.h
src/vulkan/VulkanDisposer.cpp
src/vulkan/VulkanDisposer.h
src/vulkan/VulkanDriver.cpp src/vulkan/VulkanDriver.cpp
src/vulkan/VulkanDriver.h src/vulkan/VulkanDriver.h
src/vulkan/VulkanDriverFactory.h src/vulkan/VulkanDriverFactory.h
@@ -174,36 +184,32 @@ if (FILAMENT_SUPPORTS_VULKAN)
src/vulkan/VulkanFboCache.h src/vulkan/VulkanFboCache.h
src/vulkan/VulkanHandles.cpp src/vulkan/VulkanHandles.cpp
src/vulkan/VulkanHandles.h src/vulkan/VulkanHandles.h
src/vulkan/VulkanImageUtility.cpp
src/vulkan/VulkanImageUtility.h
src/vulkan/VulkanMemory.h src/vulkan/VulkanMemory.h
src/vulkan/VulkanMemory.cpp src/vulkan/VulkanMemory.cpp
src/vulkan/VulkanPipelineCache.cpp src/vulkan/VulkanPipelineCache.cpp
src/vulkan/VulkanPipelineCache.h src/vulkan/VulkanPipelineCache.h
src/vulkan/VulkanPlatform.cpp
src/vulkan/VulkanSamplerCache.cpp src/vulkan/VulkanSamplerCache.cpp
src/vulkan/VulkanSamplerCache.h src/vulkan/VulkanSamplerCache.h
src/vulkan/VulkanStagePool.cpp src/vulkan/VulkanStagePool.cpp
src/vulkan/VulkanStagePool.h src/vulkan/VulkanStagePool.h
src/vulkan/VulkanSwapChain.cpp src/vulkan/VulkanSwapChain.cpp
src/vulkan/VulkanSwapChain.h src/vulkan/VulkanSwapChain.h
src/vulkan/VulkanReadPixels.cpp
src/vulkan/VulkanReadPixels.h
src/vulkan/VulkanResourceAllocator.h
src/vulkan/VulkanResources.cpp
src/vulkan/VulkanResources.h
src/vulkan/VulkanTexture.cpp src/vulkan/VulkanTexture.cpp
src/vulkan/VulkanTexture.h src/vulkan/VulkanTexture.h
src/vulkan/VulkanUtility.cpp src/vulkan/VulkanUtility.cpp
src/vulkan/VulkanUtility.h src/vulkan/VulkanUtility.h
) )
if (LINUX) if (ANDROID OR LINUX OR WIN32)
if (FILAMENT_SUPPORTS_WAYLAND) list(APPEND SRCS src/vulkan/platform/VulkanPlatformAndroidLinuxWindows.cpp)
list(APPEND SRCS src/vulkan/PlatformVkLinuxWayland.cpp) elseif (APPLE OR IOS)
elseif (FILAMENT_SUPPORTS_X11) list(APPEND SRCS src/vulkan/platform/VulkanPlatformApple.mm)
list(APPEND SRCS src/vulkan/PlatformVkLinuxX11.cpp)
endif()
elseif (APPLE AND NOT IOS)
list(APPEND SRCS src/vulkan/PlatformVkCocoa.mm)
elseif (IOS)
list(APPEND SRCS src/vulkan/PlatformVkCocoaTouch.mm)
elseif (ANDROID)
list(APPEND SRCS src/vulkan/PlatformVkAndroid.cpp)
elseif (WIN32)
list(APPEND SRCS src/vulkan/PlatformVkWindows.cpp)
endif() endif()
endif() endif()
@@ -332,6 +338,7 @@ elseif(WEBGL)
else() else()
set(OPTIMIZATION_FLAGS set(OPTIMIZATION_FLAGS
-ffast-math -ffast-math
-fno-finite-math-only
-ffp-contract=fast -ffp-contract=fast
# TODO: aggressive vectorization is currently broken on Android # TODO: aggressive vectorization is currently broken on Android
# -fslp-vectorize-aggressive # -fslp-vectorize-aggressive
@@ -66,7 +66,7 @@ public:
virtual void post(void* user, Callback callback) = 0; virtual void post(void* user, Callback callback) = 0;
protected: protected:
virtual ~CallbackHandler(); virtual ~CallbackHandler() = default;
}; };
} // namespace filament::backend } // namespace filament::backend

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