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
4563 changed files with 270011 additions and 7833 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.
+6
View File
@@ -7,3 +7,9 @@ for next branch cut* header.
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md). 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 -2
View File
@@ -31,7 +31,7 @@ repositories {
} }
dependencies { dependencies {
implementation 'com.google.android.filament:filament-android:1.33.0' implementation 'com.google.android.filament:filament-android:1.42.0'
} }
``` ```
@@ -40,6 +40,7 @@ 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`. |
| [![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. |
@@ -50,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.33.0' 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:
+82
View File
@@ -7,6 +7,88 @@ 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 ## v1.33.0
- materials: prepare ES2 support [⚠️ **New Material Version**] - materials: prepare ES2 support [⚠️ **New Material Version**]
+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
``` ```
+11 -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}"
} }
@@ -151,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
@@ -194,6 +195,7 @@ subprojects {
} }
ndk { ndk {
//noinspection ChromeOsAbiSupport
abiFilters(*rootProject.ext.abis) abiFilters(*rootProject.ext.abis)
} }
@@ -214,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);
} }
+30 -1
View File
@@ -317,8 +317,9 @@ 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 cutOffDistance, jfloat distance, jfloat maximumOpacity, jfloat height, jfloat heightFalloff, jfloat cutOffDistance,
jfloat r, 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, .cutOffDistance = cutOffDistance,
@@ -330,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);
@@ -486,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.
@@ -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}.
* *
@@ -966,6 +968,7 @@ public class View {
options.color[0], options.color[1], options.color[2], 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);
} }
@@ -1095,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;
@@ -1108,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() {
@@ -1158,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 cutOffDistance, 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);
@@ -1173,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.
@@ -1328,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;
/** /**
@@ -1469,9 +1533,31 @@ public class View {
/** /**
* The fog color will be sampled from the IBL in the view direction and tinted by `color`. * 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. * Depending on the scene this can produce very convincing results.
* This simulate a more anisotropic phase-function. *
* This simulates a more anisotropic phase-function.
*
* `fogColorFromIbl` is ignored when skyTexture is specified.
*
* @see skyColor
*/ */
public boolean fogColorFromIbl = false; public boolean fogColorFromIbl = false;
/**
* 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 * Enable or disable large-scale fog
*/ */
@@ -1900,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.33.0 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
+34 -1
View File
@@ -1139,7 +1139,8 @@ 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
@@ -1158,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 {
@@ -2372,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:
@@ -2584,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.
+145 -145
View File
@@ -44,7 +44,7 @@ fragment {
</pre></div> </pre></div>
<p>Next, invoke <code>matc</code> as follows.</p> <p>Next, invoke <code>matc</code> as follows.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>matc<span style="color: #bbbbbb"> </span>-a<span style="color: #bbbbbb"> </span>opengl<span style="color: #bbbbbb"> </span>-p<span style="color: #bbbbbb"> </span>mobile<span style="color: #bbbbbb"> </span>-o<span style="color: #bbbbbb"> </span>plastic.filamat<span style="color: #bbbbbb"> </span>plastic.mat <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>matc -a opengl -p mobile -o plastic.filamat plastic.mat
</pre></div> </pre></div>
<p>You should now have a material archive in your working directory, which we&#x27;ll use later in the <p>You should now have a material archive in your working directory, which we&#x27;ll use later in the
@@ -53,7 +53,7 @@ tutorial.</p>
<p>Next we&#x27;ll use Filament&#x27;s <code>cmgen</code> tool to consume a HDR environment map in latlong format, and <p>Next we&#x27;ll use Filament&#x27;s <code>cmgen</code> tool to consume a HDR environment map in latlong format, and
produce two cubemap files: a mipmapped IBL and a blurry skybox.</p> produce two cubemap files: a mipmapped IBL and a blurry skybox.</p>
<p>Download <a href="//github.com/google/filament/blob/main/third_party/environments/pillars_2k.hdr">pillars_2k.hdr</a>, then invoke the following command in your terminal.</p> <p>Download <a href="//github.com/google/filament/blob/main/third_party/environments/pillars_2k.hdr">pillars_2k.hdr</a>, then invoke the following command in your terminal.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>cmgen<span style="color: #bbbbbb"> </span>-x<span style="color: #bbbbbb"> </span>pillars_2k<span style="color: #bbbbbb"> </span>--format<span style="color: #666666">=</span>ktx<span style="color: #bbbbbb"> </span>--size<span style="color: #666666">=256</span><span style="color: #bbbbbb"> </span>--extract-blur<span style="color: #666666">=0</span>.1<span style="color: #bbbbbb"> </span>pillars_2k.hdr <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>cmgen -x pillars_2k --format<span style="color: #666666">=</span>ktx --size<span style="color: #666666">=256</span> --extract-blur<span style="color: #666666">=0</span>.1 pillars_2k.hdr
</pre></div> </pre></div>
<p>You should now have a <code>pillars_2k</code> folder containing a couple KTX files for the IBL and skybox, as <p>You should now have a <code>pillars_2k</code> folder containing a couple KTX files for the IBL and skybox, as
@@ -61,81 +61,81 @@ well as a text file with spherical harmonics coefficients. You can discard the t
IBL KTX contains these coefficients in its metadata.</p> IBL KTX contains these coefficients in its metadata.</p>
<h2>Create JavaScript</h2> <h2>Create JavaScript</h2>
<p>Next, create <code>redball.js</code> with the following content.</p> <p>Next, create <code>redball.js</code> with the following content.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>environ<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">&#39;pillars_2k&#39;</span>; <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>environ<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">&#39;pillars_2k&#39;</span>;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>ibl_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">_ibl.ktx`</span>; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>ibl_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">_ibl.ktx`</span>;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>sky_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">_skybox.ktx`</span>; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>sky_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">_skybox.ktx`</span>;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>filamat_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">&#39;plastic.filamat&#39;</span> <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>filamat_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">&#39;plastic.filamat&#39;</span><span style="color: #bbbbbb"></span>
Filament.init([<span style="color: #bbbbbb"> </span>filamat_url,<span style="color: #bbbbbb"> </span>ibl_url,<span style="color: #bbbbbb"> </span>sky_url<span style="color: #bbbbbb"> </span>],<span style="color: #bbbbbb"> </span>()<span style="color: #bbbbbb"> </span>=&gt;<span style="color: #bbbbbb"> </span>{ Filament.init([<span style="color: #bbbbbb"> </span>filamat_url,<span style="color: #bbbbbb"> </span>ibl_url,<span style="color: #bbbbbb"> </span>sky_url<span style="color: #bbbbbb"> </span>],<span style="color: #bbbbbb"> </span>()<span style="color: #bbbbbb"> </span>=&gt;<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// Create some global aliases to enums for convenience.</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// Create some global aliases to enums for convenience.</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.VertexAttribute<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.VertexAttribute; <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.VertexAttribute<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.VertexAttribute;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.AttributeType<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.VertexBuffer$AttributeType; <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.AttributeType<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.VertexBuffer$AttributeType;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.PrimitiveType<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.RenderableManager$PrimitiveType; <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.PrimitiveType<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.RenderableManager$PrimitiveType;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.IndexType<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.IndexBuffer$IndexType; <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.IndexType<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.IndexBuffer$IndexType;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.Fov<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Camera$Fov; <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.Fov<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Camera$Fov;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.LightType<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.LightManager$Type; <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.LightType<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.LightManager$Type;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// Obtain the canvas DOM object and pass it to the App.</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// Obtain the canvas DOM object and pass it to the App.</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>canvas<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">document</span>.getElementsByTagName(<span style="color: #BA2121">&#39;canvas&#39;</span>)[<span style="color: #666666">0</span>]; <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>canvas<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">document</span>.getElementsByTagName(<span style="color: #BA2121">&#39;canvas&#39;</span>)[<span style="color: #666666">0</span>];<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.app<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>App(canvas); <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.app<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>App(canvas);<span style="color: #bbbbbb"></span>
}<span style="color: #bbbbbb"> </span>); }<span style="color: #bbbbbb"> </span>);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">class</span><span style="color: #bbbbbb"> </span>App<span style="color: #bbbbbb"> </span>{ <span style="color: #008000; font-weight: bold">class</span><span style="color: #bbbbbb"> </span>App<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">constructor</span>(canvas)<span style="color: #bbbbbb"> </span>{ <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">constructor</span>(canvas)<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>canvas; <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>canvas;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>engine<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Engine.create(canvas); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>engine<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Engine.create(canvas);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>scene<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createScene(); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>scene<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createScene();<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: create material</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: create material</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: create sphere</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: create sphere</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: create lights</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: create lights</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: create IBL</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: create IBL</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: create skybox</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: create skybox</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.swapChain<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createSwapChain(); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.swapChain<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createSwapChain();<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.renderer<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createRenderer(); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.renderer<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createRenderer();<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.camera<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createCamera(Filament.EntityManager.get().create()); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.camera<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createCamera(Filament.EntityManager.get().create());<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createView(); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createView();<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view.setCamera(<span style="color: #008000; font-weight: bold">this</span>.camera); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view.setCamera(<span style="color: #008000; font-weight: bold">this</span>.camera);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view.setScene(scene); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view.setScene(scene);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize(); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize();<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.render<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.render.bind(<span style="color: #008000; font-weight: bold">this</span>); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.render<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.render.bind(<span style="color: #008000; font-weight: bold">this</span>);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize.bind(<span style="color: #008000; font-weight: bold">this</span>); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize.bind(<span style="color: #008000; font-weight: bold">this</span>);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.addEventListener(<span style="color: #BA2121">&#39;resize&#39;</span>,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize); <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.addEventListener(<span style="color: #BA2121">&#39;resize&#39;</span>,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render); <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>} <span style="color: #bbbbbb"> </span>}<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>render()<span style="color: #bbbbbb"> </span>{ <span style="color: #bbbbbb"> </span>render()<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>eye<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">4</span>],<span style="color: #bbbbbb"> </span>center<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>],<span style="color: #bbbbbb"> </span>up<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>]; <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>eye<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">4</span>],<span style="color: #bbbbbb"> </span>center<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>],<span style="color: #bbbbbb"> </span>up<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>];<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>radians<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">Date</span>.now()<span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span><span style="color: #666666">10000</span>; <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>radians<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">Date</span>.now()<span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span><span style="color: #666666">10000</span>;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>vec3.rotateY(eye,<span style="color: #bbbbbb"> </span>eye,<span style="color: #bbbbbb"> </span>center,<span style="color: #bbbbbb"> </span>radians); <span style="color: #bbbbbb"> </span>vec3.rotateY(eye,<span style="color: #bbbbbb"> </span>eye,<span style="color: #bbbbbb"> </span>center,<span style="color: #bbbbbb"> </span>radians);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.camera.lookAt(eye,<span style="color: #bbbbbb"> </span>center,<span style="color: #bbbbbb"> </span>up); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.camera.lookAt(eye,<span style="color: #bbbbbb"> </span>center,<span style="color: #bbbbbb"> </span>up);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.renderer.render(<span style="color: #008000; font-weight: bold">this</span>.swapChain,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.renderer.render(<span style="color: #008000; font-weight: bold">this</span>.swapChain,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render); <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>} <span style="color: #bbbbbb"> </span>}<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>resize()<span style="color: #bbbbbb"> </span>{ <span style="color: #bbbbbb"> </span>resize()<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>dpr<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.devicePixelRatio; <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>dpr<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.devicePixelRatio;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>width<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas.width<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.innerWidth<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span>dpr; <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>width<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas.width<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.innerWidth<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span>dpr;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>height<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas.height<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.innerHeight<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span>dpr; <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>height<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas.height<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.innerHeight<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span>dpr;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view.setViewport([<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>width,<span style="color: #bbbbbb"> </span>height]); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view.setViewport([<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>width,<span style="color: #bbbbbb"> </span>height]);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.camera.setProjectionFov(<span style="color: #666666">45</span>,<span style="color: #bbbbbb"> </span>width<span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span>height,<span style="color: #bbbbbb"> </span><span style="color: #666666">1.0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">10.0</span>,<span style="color: #bbbbbb"> </span>Fov.VERTICAL); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.camera.setProjectionFov(<span style="color: #666666">45</span>,<span style="color: #bbbbbb"> </span>width<span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span>height,<span style="color: #bbbbbb"> </span><span style="color: #666666">1.0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">10.0</span>,<span style="color: #bbbbbb"> </span>Fov.VERTICAL);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>} <span style="color: #bbbbbb"> </span>}<span style="color: #bbbbbb"></span>
} }<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>The above boilerplate should be familiar to you from the previous tutorial, although it loads in a <p>The above boilerplate should be familiar to you from the previous tutorial, although it loads in a
new set of assets. We also added some animation to the camera.</p> new set of assets. We also added some animation to the camera.</p>
<p>Next let&#x27;s create a material instance from the package that we built at the beginning the tutorial. <p>Next let&#x27;s create a material instance from the package that we built at the beginning the tutorial.
Replace the <strong>create material</strong> comment with the following snippet.</p> Replace the <strong>create material</strong> comment with the following snippet.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>material<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createMaterial(filamat_url); <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>material<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createMaterial(filamat_url);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>matinstance<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>material.createInstance(); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>matinstance<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>material.createInstance();<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>red<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0.8</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.0</span>]; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>red<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0.8</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.0</span>];<span style="color: #bbbbbb"></span>
matinstance.setColor3Parameter(<span style="color: #BA2121">&#39;baseColor&#39;</span>,<span style="color: #bbbbbb"> </span>Filament.RgbType.sRGB,<span style="color: #bbbbbb"> </span>red); matinstance.setColor3Parameter(<span style="color: #BA2121">&#39;baseColor&#39;</span>,<span style="color: #bbbbbb"> </span>Filament.RgbType.sRGB,<span style="color: #bbbbbb"> </span>red);<span style="color: #bbbbbb"></span>
matinstance.setFloatParameter(<span style="color: #BA2121">&#39;roughness&#39;</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.5</span>); matinstance.setFloatParameter(<span style="color: #BA2121">&#39;roughness&#39;</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.5</span>);<span style="color: #bbbbbb"></span>
matinstance.setFloatParameter(<span style="color: #BA2121">&#39;clearCoat&#39;</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1.0</span>); matinstance.setFloatParameter(<span style="color: #BA2121">&#39;clearCoat&#39;</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1.0</span>);<span style="color: #bbbbbb"></span>
matinstance.setFloatParameter(<span style="color: #BA2121">&#39;clearCoatRoughness&#39;</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.3</span>); matinstance.setFloatParameter(<span style="color: #BA2121">&#39;clearCoatRoughness&#39;</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.3</span>);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>The next step is to create a renderable for the sphere. To help with this, we&#x27;ll use the <code>IcoSphere</code> <p>The next step is to create a renderable for the sphere. To help with this, we&#x27;ll use the <code>IcoSphere</code>
@@ -149,33 +149,33 @@ as quaternions.</li>
</ul> </ul>
<p>Let&#x27;s go ahead use these arrays to build the vertex buffer and index buffer. Replace <strong>create <p>Let&#x27;s go ahead use these arrays to build the vertex buffer and index buffer. Replace <strong>create
sphere</strong> with the following snippet.</p> sphere</strong> with the following snippet.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>renderable<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.EntityManager.get().create(); <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>renderable<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.EntityManager.get().create();<span style="color: #bbbbbb"></span>
scene.addEntity(renderable); scene.addEntity(renderable);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>icosphere<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>Filament.IcoSphere(<span style="color: #666666">5</span>); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>icosphere<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>Filament.IcoSphere(<span style="color: #666666">5</span>);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>vb<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.VertexBuffer.Builder() <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>vb<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.VertexBuffer.Builder()<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.vertexCount(icosphere.vertices.length<span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span><span style="color: #666666">3</span>) <span style="color: #bbbbbb"> </span>.vertexCount(icosphere.vertices.length<span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span><span style="color: #666666">3</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.bufferCount(<span style="color: #666666">2</span>) <span style="color: #bbbbbb"> </span>.bufferCount(<span style="color: #666666">2</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.attribute(VertexAttribute.POSITION,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>AttributeType.FLOAT3,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>) <span style="color: #bbbbbb"> </span>.attribute(VertexAttribute.POSITION,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>AttributeType.FLOAT3,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.attribute(VertexAttribute.TANGENTS,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span>AttributeType.SHORT4,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>) <span style="color: #bbbbbb"> </span>.attribute(VertexAttribute.TANGENTS,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span>AttributeType.SHORT4,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.normalized(VertexAttribute.TANGENTS) <span style="color: #bbbbbb"> </span>.normalized(VertexAttribute.TANGENTS)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.build(engine); <span style="color: #bbbbbb"> </span>.build(engine);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>ib<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.IndexBuffer.Builder() <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>ib<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.IndexBuffer.Builder()<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.indexCount(icosphere.triangles.length) <span style="color: #bbbbbb"> </span>.indexCount(icosphere.triangles.length)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.bufferType(IndexType.USHORT) <span style="color: #bbbbbb"> </span>.bufferType(IndexType.USHORT)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.build(engine); <span style="color: #bbbbbb"> </span>.build(engine);<span style="color: #bbbbbb"></span>
vb.setBufferAt(engine,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>icosphere.vertices); vb.setBufferAt(engine,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>icosphere.vertices);<span style="color: #bbbbbb"></span>
vb.setBufferAt(engine,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span>icosphere.tangents); vb.setBufferAt(engine,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span>icosphere.tangents);<span style="color: #bbbbbb"></span>
ib.setBuffer(engine,<span style="color: #bbbbbb"> </span>icosphere.triangles); ib.setBuffer(engine,<span style="color: #bbbbbb"> </span>icosphere.triangles);<span style="color: #bbbbbb"></span>
Filament.RenderableManager.Builder(<span style="color: #666666">1</span>) Filament.RenderableManager.Builder(<span style="color: #666666">1</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.boundingBox({<span style="color: #bbbbbb"> </span>center<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">-1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">-1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">-1</span>],<span style="color: #bbbbbb"> </span>halfExtent<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>]<span style="color: #bbbbbb"> </span>}) <span style="color: #bbbbbb"> </span>.boundingBox({<span style="color: #bbbbbb"> </span>center<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">-1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">-1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">-1</span>],<span style="color: #bbbbbb"> </span>halfExtent<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>]<span style="color: #bbbbbb"> </span>})<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.material(<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>matinstance) <span style="color: #bbbbbb"> </span>.material(<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>matinstance)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.geometry(<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>PrimitiveType.TRIANGLES,<span style="color: #bbbbbb"> </span>vb,<span style="color: #bbbbbb"> </span>ib) <span style="color: #bbbbbb"> </span>.geometry(<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>PrimitiveType.TRIANGLES,<span style="color: #bbbbbb"> </span>vb,<span style="color: #bbbbbb"> </span>ib)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.build(engine,<span style="color: #bbbbbb"> </span>renderable); <span style="color: #bbbbbb"> </span>.build(engine,<span style="color: #bbbbbb"> </span>renderable);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>At this point, the app is rendering a sphere, but it is black so it doesn&#x27;t show up. To prove that <p>At this point, the app is rendering a sphere, but it is black so it doesn&#x27;t show up. To prove that
@@ -185,94 +185,94 @@ did in the first tutorial.</p>
<p>In this section we will create some directional light sources, as well as an image-based light (IBL) <p>In this section we will create some directional light sources, as well as an image-based light (IBL)
defined by one of the KTX files we built at the start of the demo. First, replace the <strong>create defined by one of the KTX files we built at the start of the demo. First, replace the <strong>create
lights</strong> comment with the following snippet.</p> lights</strong> comment with the following snippet.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>sunlight<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.EntityManager.get().create(); <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>sunlight<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.EntityManager.get().create();<span style="color: #bbbbbb"></span>
scene.addEntity(sunlight); scene.addEntity(sunlight);<span style="color: #bbbbbb"></span>
Filament.LightManager.Builder(LightType.SUN) Filament.LightManager.Builder(LightType.SUN)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.color([<span style="color: #666666">0.98</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.92</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.89</span>]) <span style="color: #bbbbbb"> </span>.color([<span style="color: #666666">0.98</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.92</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.89</span>])<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.intensity(<span style="color: #666666">110000.0</span>) <span style="color: #bbbbbb"> </span>.intensity(<span style="color: #666666">110000.0</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.direction([<span style="color: #666666">0.6</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">-1.0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">-0.8</span>]) <span style="color: #bbbbbb"> </span>.direction([<span style="color: #666666">0.6</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">-1.0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">-0.8</span>])<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.sunAngularRadius(<span style="color: #666666">1.9</span>) <span style="color: #bbbbbb"> </span>.sunAngularRadius(<span style="color: #666666">1.9</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.sunHaloSize(<span style="color: #666666">10.0</span>) <span style="color: #bbbbbb"> </span>.sunHaloSize(<span style="color: #666666">10.0</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.sunHaloFalloff(<span style="color: #666666">80.0</span>) <span style="color: #bbbbbb"> </span>.sunHaloFalloff(<span style="color: #666666">80.0</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.build(engine,<span style="color: #bbbbbb"> </span>sunlight); <span style="color: #bbbbbb"> </span>.build(engine,<span style="color: #bbbbbb"> </span>sunlight);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>backlight<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.EntityManager.get().create(); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>backlight<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.EntityManager.get().create();<span style="color: #bbbbbb"></span>
scene.addEntity(backlight); scene.addEntity(backlight);<span style="color: #bbbbbb"></span>
Filament.LightManager.Builder(LightType.DIRECTIONAL) Filament.LightManager.Builder(LightType.DIRECTIONAL)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.direction([<span style="color: #666666">-1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>]) <span style="color: #bbbbbb"> </span>.direction([<span style="color: #666666">-1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>])<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.intensity(<span style="color: #666666">50000.0</span>) <span style="color: #bbbbbb"> </span>.intensity(<span style="color: #666666">50000.0</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.build(engine,<span style="color: #bbbbbb"> </span>backlight); <span style="color: #bbbbbb"> </span>.build(engine,<span style="color: #bbbbbb"> </span>backlight);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>The <code>SUN</code> light source is similar to the <code>DIRECTIONAL</code> light source, but has some extra <p>The <code>SUN</code> light source is similar to the <code>DIRECTIONAL</code> light source, but has some extra
parameters because Filament will automatically draw a disk into the skybox.</p> parameters because Filament will automatically draw a disk into the skybox.</p>
<p>Next we need to create an <code>IndirectLight</code> object from the KTX IBL. One way of doing this is the <p>Next we need to create an <code>IndirectLight</code> object from the KTX IBL. One way of doing this is the
following (don&#x27;t type this out, there&#x27;s an easier way).</p> following (don&#x27;t type this out, there&#x27;s an easier way).</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>format<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.PixelDataFormat.RGB; <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>format<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.PixelDataFormat.RGB;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>datatype<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.PixelDataType.UINT_10F_11F_11F_REV; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>datatype<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.PixelDataType.UINT_10F_11F_11F_REV;<span style="color: #bbbbbb"></span>
<span style="color: #3D7B7B; font-style: italic">// Create a Texture object for the mipmapped cubemap.</span> <span style="color: #3D7B7B; font-style: italic">// Create a Texture object for the mipmapped cubemap.</span><span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>ibl_package<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Buffer(Filament.assets[ibl_url]); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>ibl_package<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Buffer(Filament.assets[ibl_url]);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>iblktx<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>Filament.Ktx1Bundle(ibl_package); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>iblktx<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>Filament.Ktx1Bundle(ibl_package);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>ibltex<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Texture.Builder() <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>ibltex<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Texture.Builder()<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.width(iblktx.info().pixelWidth) <span style="color: #bbbbbb"> </span>.width(iblktx.info().pixelWidth)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.height(iblktx.info().pixelHeight) <span style="color: #bbbbbb"> </span>.height(iblktx.info().pixelHeight)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.levels(iblktx.getNumMipLevels()) <span style="color: #bbbbbb"> </span>.levels(iblktx.getNumMipLevels())<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.sampler(Filament.Texture$Sampler.SAMPLER_CUBEMAP) <span style="color: #bbbbbb"> </span>.sampler(Filament.Texture$Sampler.SAMPLER_CUBEMAP)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.format(Filament.Texture$InternalFormat.RGBA8) <span style="color: #bbbbbb"> </span>.format(Filament.Texture$InternalFormat.RGBA8)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.build(engine); <span style="color: #bbbbbb"> </span>.build(engine);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">for</span><span style="color: #bbbbbb"> </span>(<span style="color: #008000; font-weight: bold">let</span><span style="color: #bbbbbb"> </span>level<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>;<span style="color: #bbbbbb"> </span>level<span style="color: #bbbbbb"> </span><span style="color: #666666">&lt;</span><span style="color: #bbbbbb"> </span>iblktx.getNumMipLevels();<span style="color: #bbbbbb"> </span><span style="color: #666666">++</span>level)<span style="color: #bbbbbb"> </span>{ <span style="color: #008000; font-weight: bold">for</span><span style="color: #bbbbbb"> </span>(<span style="color: #008000; font-weight: bold">let</span><span style="color: #bbbbbb"> </span>level<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>;<span style="color: #bbbbbb"> </span>level<span style="color: #bbbbbb"> </span><span style="color: #666666">&lt;</span><span style="color: #bbbbbb"> </span>iblktx.getNumMipLevels();<span style="color: #bbbbbb"> </span><span style="color: #666666">++</span>level)<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>uint8array<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>iblktx.getCubeBlob(level).getBytes(); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>uint8array<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>iblktx.getCubeBlob(level).getBytes();<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>pixelbuffer<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.PixelBuffer(uint8array,<span style="color: #bbbbbb"> </span>format,<span style="color: #bbbbbb"> </span>datatype); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>pixelbuffer<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.PixelBuffer(uint8array,<span style="color: #bbbbbb"> </span>format,<span style="color: #bbbbbb"> </span>datatype);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>ibltex.setImageCube(engine,<span style="color: #bbbbbb"> </span>level,<span style="color: #bbbbbb"> </span>pixelbuffer); <span style="color: #bbbbbb"> </span>ibltex.setImageCube(engine,<span style="color: #bbbbbb"> </span>level,<span style="color: #bbbbbb"> </span>pixelbuffer);<span style="color: #bbbbbb"></span>
} }<span style="color: #bbbbbb"></span>
<span style="color: #3D7B7B; font-style: italic">// Parse the spherical harmonics metadata.</span> <span style="color: #3D7B7B; font-style: italic">// Parse the spherical harmonics metadata.</span><span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>shstring<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>iblktx.getMetadata(<span style="color: #BA2121">&#39;sh&#39;</span>); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>shstring<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>iblktx.getMetadata(<span style="color: #BA2121">&#39;sh&#39;</span>);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>shfloats<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>shstring.split(<span style="color: #A45A77">/\s/</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">9</span><span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span><span style="color: #666666">3</span>).map(<span style="color: #008000">parseFloat</span>); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>shfloats<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>shstring.split(<span style="color: #A45A77">/\s/</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">9</span><span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span><span style="color: #666666">3</span>).map(<span style="color: #008000">parseFloat</span>);<span style="color: #bbbbbb"></span>
<span style="color: #3D7B7B; font-style: italic">// Build the IBL object and insert it into the scene.</span> <span style="color: #3D7B7B; font-style: italic">// Build the IBL object and insert it into the scene.</span><span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>indirectLight<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.IndirectLight.Builder() <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>indirectLight<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.IndirectLight.Builder()<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.reflections(ibltex) <span style="color: #bbbbbb"> </span>.reflections(ibltex)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.irradianceSh(<span style="color: #666666">3</span>,<span style="color: #bbbbbb"> </span>shfloats) <span style="color: #bbbbbb"> </span>.irradianceSh(<span style="color: #666666">3</span>,<span style="color: #bbbbbb"> </span>shfloats)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.intensity(<span style="color: #666666">50000.0</span>) <span style="color: #bbbbbb"> </span>.intensity(<span style="color: #666666">50000.0</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.build(engine); <span style="color: #bbbbbb"> </span>.build(engine);<span style="color: #bbbbbb"></span>
scene.setIndirectLight(indirectLight); scene.setIndirectLight(indirectLight);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>Filament provides a JavaScript utility to make this simpler, <p>Filament provides a JavaScript utility to make this simpler,
simply replace the <strong>create IBL</strong> comment with the following snippet.</p> simply replace the <strong>create IBL</strong> comment with the following snippet.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>indirectLight<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createIblFromKtx1(ibl_url); <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>indirectLight<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createIblFromKtx1(ibl_url);<span style="color: #bbbbbb"></span>
indirectLight.setIntensity(<span style="color: #666666">50000</span>); indirectLight.setIntensity(<span style="color: #666666">50000</span>);<span style="color: #bbbbbb"></span>
scene.setIndirectLight(indirectLight); scene.setIndirectLight(indirectLight);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<h2>Add background</h2> <h2>Add background</h2>
<p>At this point you can run the demo and you should see a red plastic ball against a black background. <p>At this point you can run the demo and you should see a red plastic ball against a black background.
Without a skybox, the reflections on the ball are not representative of its surroundings. Without a skybox, the reflections on the ball are not representative of its surroundings.
Here&#x27;s one way to create a texture for the skybox:</p> Here&#x27;s one way to create a texture for the skybox:</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>sky_package<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Buffer(Filament.assets[sky_url]); <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>sky_package<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Buffer(Filament.assets[sky_url]);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>skyktx<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>Filament.Ktx1Bundle(sky_package); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>skyktx<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>Filament.Ktx1Bundle(sky_package);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>skytex<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Texture.Builder() <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>skytex<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Texture.Builder()<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.width(skyktx.info().pixelWidth) <span style="color: #bbbbbb"> </span>.width(skyktx.info().pixelWidth)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.height(skyktx.info().pixelHeight) <span style="color: #bbbbbb"> </span>.height(skyktx.info().pixelHeight)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.levels(<span style="color: #666666">1</span>) <span style="color: #bbbbbb"> </span>.levels(<span style="color: #666666">1</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.sampler(Filament.Texture$Sampler.SAMPLER_CUBEMAP) <span style="color: #bbbbbb"> </span>.sampler(Filament.Texture$Sampler.SAMPLER_CUBEMAP)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.format(Filament.Texture$InternalFormat.RGBA8) <span style="color: #bbbbbb"> </span>.format(Filament.Texture$InternalFormat.RGBA8)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.build(engine); <span style="color: #bbbbbb"> </span>.build(engine);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>uint8array<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>skyktx.getCubeBlob(<span style="color: #666666">0</span>).getBytes(); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>uint8array<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>skyktx.getCubeBlob(<span style="color: #666666">0</span>).getBytes();<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>pixelbuffer<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.PixelBuffer(uint8array,<span style="color: #bbbbbb"> </span>format,<span style="color: #bbbbbb"> </span>datatype); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>pixelbuffer<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.PixelBuffer(uint8array,<span style="color: #bbbbbb"> </span>format,<span style="color: #bbbbbb"> </span>datatype);<span style="color: #bbbbbb"></span>
skytex.setImageCube(engine,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>pixelbuffer); skytex.setImageCube(engine,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>pixelbuffer);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>Filament provides a Javascript utility to make this easier. <p>Filament provides a Javascript utility to make this easier.
Replace <strong>create skybox</strong> with the following.</p> Replace <strong>create skybox</strong> with the following.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>skybox<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createSkyFromKtx1(sky_url); <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>skybox<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createSkyFromKtx1(sky_url);<span style="color: #bbbbbb"></span>
scene.setSkybox(skybox); scene.setSkybox(skybox);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>That&#x27;s it, we now have a shiny red ball floating in an environment! The complete JavaScript file is <p>That&#x27;s it, we now have a shiny red ball floating in an environment! The complete JavaScript file is
+108 -108
View File
@@ -15,7 +15,7 @@ we&#x27;ll also be using <code>filamesh</code> and <code>mipgen</code>.</p>
<p>Filament does not have an asset loading system, but it does provide a binary mesh format <p>Filament does not have an asset loading system, but it does provide a binary mesh format
called <code>filamesh</code> for simple use cases. Let&#x27;s create a compressed filamesh file for suzanne by called <code>filamesh</code> for simple use cases. Let&#x27;s create a compressed filamesh file for suzanne by
converting <a href="https://github.com/google/filament/blob/main/assets/models/monkey/monkey.obj">this OBJ file</a>:</p> converting <a href="https://github.com/google/filament/blob/main/assets/models/monkey/monkey.obj">this OBJ file</a>:</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>filamesh<span style="color: #bbbbbb"> </span>--compress<span style="color: #bbbbbb"> </span>monkey.obj<span style="color: #bbbbbb"> </span>suzanne.filamesh <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>filamesh --compress monkey.obj suzanne.filamesh
</pre></div> </pre></div>
<h2>Create mipmapped textures</h2> <h2>Create mipmapped textures</h2>
@@ -23,26 +23,26 @@ converting <a href="https://github.com/google/filament/blob/main/assets/models/m
non-compressed variants for each texture, since not all platforms support the same compression non-compressed variants for each texture, since not all platforms support the same compression
formats. First copy over the PNG files from the <a href="https://github.com/google/filament/blob/main/assets/models/monkey">monkey folder</a>, then do:</p> formats. First copy over the PNG files from the <a href="https://github.com/google/filament/blob/main/assets/models/monkey">monkey folder</a>, then do:</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #3D7B7B; font-style: italic"># Create mipmaps for base color and two compressed variants.</span> <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #3D7B7B; font-style: italic"># Create mipmaps for base color and two compressed variants.</span>
mipgen<span style="color: #bbbbbb"> </span>albedo.png<span style="color: #bbbbbb"> </span>albedo.ktx mipgen albedo.png albedo.ktx
mipgen<span style="color: #bbbbbb"> </span>--compression<span style="color: #666666">=</span>astc_fast_ldr_4x4<span style="color: #bbbbbb"> </span>albedo.png<span style="color: #bbbbbb"> </span>albedo_astc.ktx mipgen --compression<span style="color: #666666">=</span>astc_fast_ldr_4x4 albedo.png albedo_astc.ktx
mipgen<span style="color: #bbbbbb"> </span>--compression<span style="color: #666666">=</span>s3tc_rgb_dxt1<span style="color: #bbbbbb"> </span>albedo.png<span style="color: #bbbbbb"> </span>albedo_s3tc_srgb.ktx mipgen --compression<span style="color: #666666">=</span>s3tc_rgb_dxt1 albedo.png albedo_s3tc_srgb.ktx
<span style="color: #3D7B7B; font-style: italic"># Create mipmaps for the normal map and a compressed variant.</span> <span style="color: #3D7B7B; font-style: italic"># Create mipmaps for the normal map and a compressed variant.</span>
mipgen<span style="color: #bbbbbb"> </span>--strip-alpha<span style="color: #bbbbbb"> </span>--kernel<span style="color: #666666">=</span>NORMALS<span style="color: #bbbbbb"> </span>--linear<span style="color: #bbbbbb"> </span>normal.png<span style="color: #bbbbbb"> </span>normal.ktx mipgen --strip-alpha --kernel<span style="color: #666666">=</span>NORMALS --linear normal.png normal.ktx
mipgen<span style="color: #bbbbbb"> </span>--strip-alpha<span style="color: #bbbbbb"> </span>--kernel<span style="color: #666666">=</span>NORMALS<span style="color: #bbbbbb"> </span>--linear<span style="color: #bbbbbb"> </span>--compression<span style="color: #666666">=</span>etc_rgb8_normalxyz_40<span style="color: #bbbbbb"> </span><span style="color: #AA5D1F; font-weight: bold">\</span> mipgen --strip-alpha --kernel<span style="color: #666666">=</span>NORMALS --linear --compression<span style="color: #666666">=</span>etc_rgb8_normalxyz_40 <span style="color: #AA5D1F; font-weight: bold">\</span>
<span style="color: #bbbbbb"> </span>normal.png<span style="color: #bbbbbb"> </span>normal_etc.ktx normal.png normal_etc.ktx
<span style="color: #3D7B7B; font-style: italic"># Create mipmaps for the single-component roughness map and a compressed variant.</span> <span style="color: #3D7B7B; font-style: italic"># Create mipmaps for the single-component roughness map and a compressed variant.</span>
mipgen<span style="color: #bbbbbb"> </span>--grayscale<span style="color: #bbbbbb"> </span>roughness.png<span style="color: #bbbbbb"> </span>roughness.ktx mipgen --grayscale roughness.png roughness.ktx
mipgen<span style="color: #bbbbbb"> </span>--grayscale<span style="color: #bbbbbb"> </span>--compression<span style="color: #666666">=</span>etc_r11_numeric_40<span style="color: #bbbbbb"> </span>roughness.png<span style="color: #bbbbbb"> </span>roughness_etc.ktx mipgen --grayscale --compression<span style="color: #666666">=</span>etc_r11_numeric_40 roughness.png roughness_etc.ktx
<span style="color: #3D7B7B; font-style: italic"># Create mipmaps for the single-component metallic map and a compressed variant.</span> <span style="color: #3D7B7B; font-style: italic"># Create mipmaps for the single-component metallic map and a compressed variant.</span>
mipgen<span style="color: #bbbbbb"> </span>--grayscale<span style="color: #bbbbbb"> </span>metallic.png<span style="color: #bbbbbb"> </span>metallic.ktx mipgen --grayscale metallic.png metallic.ktx
mipgen<span style="color: #bbbbbb"> </span>--grayscale<span style="color: #bbbbbb"> </span>--compression<span style="color: #666666">=</span>etc_r11_numeric_40<span style="color: #bbbbbb"> </span>metallic.png<span style="color: #bbbbbb"> </span>metallic_etc.ktx mipgen --grayscale --compression<span style="color: #666666">=</span>etc_r11_numeric_40 metallic.png metallic_etc.ktx
<span style="color: #3D7B7B; font-style: italic"># Create mipmaps for the single-component occlusion map and a compressed variant.</span> <span style="color: #3D7B7B; font-style: italic"># Create mipmaps for the single-component occlusion map and a compressed variant.</span>
mipgen<span style="color: #bbbbbb"> </span>--grayscale<span style="color: #bbbbbb"> </span>ao.png<span style="color: #bbbbbb"> </span>ao.ktx mipgen --grayscale ao.png ao.ktx
mipgen<span style="color: #bbbbbb"> </span>--grayscale<span style="color: #bbbbbb"> </span>--compression<span style="color: #666666">=</span>etc_r11_numeric_40<span style="color: #bbbbbb"> </span>ao.png<span style="color: #bbbbbb"> </span>ao_etc.ktx mipgen --grayscale --compression<span style="color: #666666">=</span>etc_r11_numeric_40 ao.png ao_etc.ktx
</pre></div> </pre></div>
<p>For more information on mipgen&#x27;s arguments and supported formats, do <code>mipgen --help</code>.</p> <p>For more information on mipgen&#x27;s arguments and supported formats, do <code>mipgen --help</code>.</p>
@@ -50,12 +50,12 @@ mipgen<span style="color: #bbbbbb"> </span>--grayscale<span style="color: #bbbbb
<h2>Bake environment map</h2> <h2>Bake environment map</h2>
<p>Much like the <a href="tutorial_redball.html">previous tutorial</a> we need to use Filament&#x27;s <code>cmgen</code> tool to produce cubemap files.</p> <p>Much like the <a href="tutorial_redball.html">previous tutorial</a> we need to use Filament&#x27;s <code>cmgen</code> tool to produce cubemap files.</p>
<p>Download <a href="//github.com/google/filament/blob/main/third_party/environments/venetian_crossroads_2k.hdr">venetian_crossroads_2k.hdr</a>, then invoke the following commands in your terminal.</p> <p>Download <a href="//github.com/google/filament/blob/main/third_party/environments/venetian_crossroads_2k.hdr">venetian_crossroads_2k.hdr</a>, then invoke the following commands in your terminal.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>cmgen<span style="color: #bbbbbb"> </span>-x<span style="color: #bbbbbb"> </span>.<span style="color: #bbbbbb"> </span>--format<span style="color: #666666">=</span>ktx<span style="color: #bbbbbb"> </span>--size<span style="color: #666666">=64</span><span style="color: #bbbbbb"> </span>--extract-blur<span style="color: #666666">=0</span>.1<span style="color: #bbbbbb"> </span>venetian_crossroads_2k.hdr <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>cmgen -x . --format<span style="color: #666666">=</span>ktx --size<span style="color: #666666">=64</span> --extract-blur<span style="color: #666666">=0</span>.1 venetian_crossroads_2k.hdr
<span style="color: #008000">cd</span><span style="color: #bbbbbb"> </span>venetian*<span style="color: #bbbbbb"> </span>;<span style="color: #bbbbbb"> </span>mv<span style="color: #bbbbbb"> </span>venetian*_ibl.ktx<span style="color: #bbbbbb"> </span>venetian_crossroads_2k_skybox_tiny.ktx<span style="color: #bbbbbb"> </span>;<span style="color: #bbbbbb"> </span><span style="color: #008000">cd</span><span style="color: #bbbbbb"> </span>- <span style="color: #008000">cd</span> venetian* ; mv venetian*_ibl.ktx venetian_crossroads_2k_skybox_tiny.ktx ; <span style="color: #008000">cd</span> -
cmgen<span style="color: #bbbbbb"> </span>-x<span style="color: #bbbbbb"> </span>.<span style="color: #bbbbbb"> </span>--format<span style="color: #666666">=</span>ktx<span style="color: #bbbbbb"> </span>--size<span style="color: #666666">=256</span><span style="color: #bbbbbb"> </span>--extract-blur<span style="color: #666666">=0</span>.1<span style="color: #bbbbbb"> </span>venetian_crossroads_2k.hdr cmgen -x . --format<span style="color: #666666">=</span>ktx --size<span style="color: #666666">=256</span> --extract-blur<span style="color: #666666">=0</span>.1 venetian_crossroads_2k.hdr
cmgen<span style="color: #bbbbbb"> </span>-x<span style="color: #bbbbbb"> </span>.<span style="color: #bbbbbb"> </span>--format<span style="color: #666666">=</span>ktx<span style="color: #bbbbbb"> </span>--size<span style="color: #666666">=256</span><span style="color: #bbbbbb"> </span>--extract-blur<span style="color: #666666">=0</span>.1<span style="color: #bbbbbb"> </span>venetian_crossroads_2k.hdr cmgen -x . --format<span style="color: #666666">=</span>ktx --size<span style="color: #666666">=256</span> --extract-blur<span style="color: #666666">=0</span>.1 venetian_crossroads_2k.hdr
cmgen<span style="color: #bbbbbb"> </span>-x<span style="color: #bbbbbb"> </span>.<span style="color: #bbbbbb"> </span>--format<span style="color: #666666">=</span>ktx<span style="color: #bbbbbb"> </span>--size<span style="color: #666666">=256</span><span style="color: #bbbbbb"> </span>--extract-blur<span style="color: #666666">=0</span>.1<span style="color: #bbbbbb"> </span>venetian_crossroads_2k.hdr cmgen -x . --format<span style="color: #666666">=</span>ktx --size<span style="color: #666666">=256</span> --extract-blur<span style="color: #666666">=0</span>.1 venetian_crossroads_2k.hdr
</pre></div> </pre></div>
<h2>Define textured material</h2> <h2>Define textured material</h2>
@@ -91,7 +91,7 @@ fragment {
</pre></div> </pre></div>
<p>Next, invoke <code>matc</code> as follows.</p> <p>Next, invoke <code>matc</code> as follows.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>matc<span style="color: #bbbbbb"> </span>-a<span style="color: #bbbbbb"> </span>opengl<span style="color: #bbbbbb"> </span>-p<span style="color: #bbbbbb"> </span>mobile<span style="color: #bbbbbb"> </span>-o<span style="color: #bbbbbb"> </span>textured.filamat<span style="color: #bbbbbb"> </span>textured.mat <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>matc -a opengl -p mobile -o textured.filamat textured.mat
</pre></div> </pre></div>
<p>You should now have a material archive in your working directory. For the suzanne asset, the normal <p>You should now have a material archive in your working directory. For the suzanne asset, the normal
@@ -101,62 +101,62 @@ materials, consult the official document describing the <a href="https://google.
<p>Create a text file called <code>suzanne.html</code> and copy over the HTML that we used in the <a href="tutorial_redball.html">previous <p>Create a text file called <code>suzanne.html</code> and copy over the HTML that we used in the <a href="tutorial_redball.html">previous
tutorial</a>. Change the last script tag from <code>redball.js</code> to <code>suzanne.js</code>. Next, create <code>suzanne.js</code> tutorial</a>. Change the last script tag from <code>redball.js</code> to <code>suzanne.js</code>. Next, create <code>suzanne.js</code>
with the following content.</p> with the following content.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #3D7B7B; font-style: italic">// TODO: declare asset URLs</span> <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #3D7B7B; font-style: italic">// TODO: declare asset URLs</span><span style="color: #bbbbbb"></span>
Filament.init([<span style="color: #bbbbbb"> </span>filamat_url,<span style="color: #bbbbbb"> </span>filamesh_url,<span style="color: #bbbbbb"> </span>sky_small_url,<span style="color: #bbbbbb"> </span>ibl_url<span style="color: #bbbbbb"> </span>],<span style="color: #bbbbbb"> </span>()<span style="color: #bbbbbb"> </span>=&gt;<span style="color: #bbbbbb"> </span>{ Filament.init([<span style="color: #bbbbbb"> </span>filamat_url,<span style="color: #bbbbbb"> </span>filamesh_url,<span style="color: #bbbbbb"> </span>sky_small_url,<span style="color: #bbbbbb"> </span>ibl_url<span style="color: #bbbbbb"> </span>],<span style="color: #bbbbbb"> </span>()<span style="color: #bbbbbb"> </span>=&gt;<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.app<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>App(<span style="color: #008000">document</span>.getElementsByTagName(<span style="color: #BA2121">&#39;canvas&#39;</span>)[<span style="color: #666666">0</span>]); <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.app<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>App(<span style="color: #008000">document</span>.getElementsByTagName(<span style="color: #BA2121">&#39;canvas&#39;</span>)[<span style="color: #666666">0</span>]);<span style="color: #bbbbbb"></span>
}); });<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">class</span><span style="color: #bbbbbb"> </span>App<span style="color: #bbbbbb"> </span>{ <span style="color: #008000; font-weight: bold">class</span><span style="color: #bbbbbb"> </span>App<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">constructor</span>(canvas)<span style="color: #bbbbbb"> </span>{ <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">constructor</span>(canvas)<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>canvas; <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>canvas;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Engine.create(canvas); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Engine.create(canvas);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.scene<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createScene(); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.scene<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createScene();<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>material<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createMaterial(filamat_url); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>material<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createMaterial(filamat_url);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.matinstance<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>material.createInstance(); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.matinstance<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>material.createInstance();<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>filamesh<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.loadFilamesh(filamesh_url,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.matinstance); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>filamesh<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.loadFilamesh(filamesh_url,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.matinstance);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.suzanne<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>filamesh.renderable; <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.suzanne<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>filamesh.renderable;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: create sky box and IBL</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: create sky box and IBL</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: initialize gltumble</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: initialize gltumble</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: fetch larger assets</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: fetch larger assets</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.swapChain<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createSwapChain(); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.swapChain<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createSwapChain();<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.renderer<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createRenderer(); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.renderer<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createRenderer();<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.camera<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createCamera(Filament.EntityManager.get().create()); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.camera<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createCamera(Filament.EntityManager.get().create());<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createView(); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createView();<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view.setCamera(<span style="color: #008000; font-weight: bold">this</span>.camera); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view.setCamera(<span style="color: #008000; font-weight: bold">this</span>.camera);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view.setScene(<span style="color: #008000; font-weight: bold">this</span>.scene); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view.setScene(<span style="color: #008000; font-weight: bold">this</span>.scene);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.render<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.render.bind(<span style="color: #008000; font-weight: bold">this</span>); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.render<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.render.bind(<span style="color: #008000; font-weight: bold">this</span>);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize.bind(<span style="color: #008000; font-weight: bold">this</span>); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize.bind(<span style="color: #008000; font-weight: bold">this</span>);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.addEventListener(<span style="color: #BA2121">&#39;resize&#39;</span>,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize); <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.addEventListener(<span style="color: #BA2121">&#39;resize&#39;</span>,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>eye<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">4</span>],<span style="color: #bbbbbb"> </span>center<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>],<span style="color: #bbbbbb"> </span>up<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>]; <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>eye<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">4</span>],<span style="color: #bbbbbb"> </span>center<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>],<span style="color: #bbbbbb"> </span>up<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>];<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.camera.lookAt(eye,<span style="color: #bbbbbb"> </span>center,<span style="color: #bbbbbb"> </span>up); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.camera.lookAt(eye,<span style="color: #bbbbbb"> </span>center,<span style="color: #bbbbbb"> </span>up);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize(); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize();<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render); <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>} <span style="color: #bbbbbb"> </span>}<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>render()<span style="color: #bbbbbb"> </span>{ <span style="color: #bbbbbb"> </span>render()<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: apply gltumble matrix</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: apply gltumble matrix</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.renderer.render(<span style="color: #008000; font-weight: bold">this</span>.swapChain,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.renderer.render(<span style="color: #008000; font-weight: bold">this</span>.swapChain,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render); <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>} <span style="color: #bbbbbb"> </span>}<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>resize()<span style="color: #bbbbbb"> </span>{ <span style="color: #bbbbbb"> </span>resize()<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>dpr<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.devicePixelRatio; <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>dpr<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.devicePixelRatio;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>width<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas.width<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.innerWidth<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span>dpr; <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>width<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas.width<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.innerWidth<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span>dpr;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>height<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas.height<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.innerHeight<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span>dpr; <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>height<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas.height<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.innerHeight<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span>dpr;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view.setViewport([<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>width,<span style="color: #bbbbbb"> </span>height]); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view.setViewport([<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>width,<span style="color: #bbbbbb"> </span>height]);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>aspect<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>width<span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span>height; <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>aspect<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>width<span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span>height;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>Fov<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Camera$Fov,<span style="color: #bbbbbb"> </span>fov<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>aspect<span style="color: #bbbbbb"> </span><span style="color: #666666">&lt;</span><span style="color: #bbbbbb"> </span><span style="color: #666666">1</span><span style="color: #bbbbbb"> </span><span style="color: #666666">?</span><span style="color: #bbbbbb"> </span>Fov.HORIZONTAL<span style="color: #bbbbbb"> </span><span style="color: #666666">:</span><span style="color: #bbbbbb"> </span>Fov.VERTICAL; <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>Fov<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Camera$Fov,<span style="color: #bbbbbb"> </span>fov<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>aspect<span style="color: #bbbbbb"> </span><span style="color: #666666">&lt;</span><span style="color: #bbbbbb"> </span><span style="color: #666666">1</span><span style="color: #bbbbbb"> </span><span style="color: #666666">?</span><span style="color: #bbbbbb"> </span>Fov.HORIZONTAL<span style="color: #bbbbbb"> </span><span style="color: #666666">:</span><span style="color: #bbbbbb"> </span>Fov.VERTICAL;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.camera.setProjectionFov(<span style="color: #666666">45</span>,<span style="color: #bbbbbb"> </span>aspect,<span style="color: #bbbbbb"> </span><span style="color: #666666">1.0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">10.0</span>,<span style="color: #bbbbbb"> </span>fov); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.camera.setProjectionFov(<span style="color: #666666">45</span>,<span style="color: #bbbbbb"> </span>aspect,<span style="color: #bbbbbb"> </span><span style="color: #666666">1.0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">10.0</span>,<span style="color: #bbbbbb"> </span>fov);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>} <span style="color: #bbbbbb"> </span>}<span style="color: #bbbbbb"></span>
} }<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>Our app will only require a subset of assets to be present for <code>App</code> construction. We&#x27;ll download <p>Our app will only require a subset of assets to be present for <code>App</code> construction. We&#x27;ll download
@@ -172,29 +172,29 @@ string -- which might be empty.</p>
<p>In our case, we know that our web server will have <code>astc</code> and <code>s3tc</code> variants for albedo, and <code>etc</code> <p>In our case, we know that our web server will have <code>astc</code> and <code>s3tc</code> variants for albedo, and <code>etc</code>
variants for the other textures. The uncompressed variants (empty string) are always available as a variants for the other textures. The uncompressed variants (empty string) are always available as a
last resort. Go ahead and replace the <strong>declare asset URLs</strong> comment with the following snippet.</p> last resort. Go ahead and replace the <strong>declare asset URLs</strong> comment with the following snippet.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>albedo_suffix<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.getSupportedFormatSuffix(<span style="color: #BA2121">&#39;astc s3tc_srgb&#39;</span>); <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>albedo_suffix<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.getSupportedFormatSuffix(<span style="color: #BA2121">&#39;astc s3tc_srgb&#39;</span>);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>texture_suffix<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.getSupportedFormatSuffix(<span style="color: #BA2121">&#39;etc&#39;</span>); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>texture_suffix<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.getSupportedFormatSuffix(<span style="color: #BA2121">&#39;etc&#39;</span>);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>environ<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">&#39;venetian_crossroads_2k&#39;</span> <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>environ<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">&#39;venetian_crossroads_2k&#39;</span><span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>ibl_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">_ibl.ktx`</span>; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>ibl_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">_ibl.ktx`</span>;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>sky_small_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">_skybox_tiny.ktx`</span>; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>sky_small_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">_skybox_tiny.ktx`</span>;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>sky_large_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">_skybox.ktx`</span>; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>sky_large_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">_skybox.ktx`</span>;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>albedo_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`albedo</span><span style="color: #A45A77; font-weight: bold">${</span>albedo_suffix<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>albedo_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`albedo</span><span style="color: #A45A77; font-weight: bold">${</span>albedo_suffix<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>ao_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`ao</span><span style="color: #A45A77; font-weight: bold">${</span>texture_suffix<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>ao_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`ao</span><span style="color: #A45A77; font-weight: bold">${</span>texture_suffix<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>metallic_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`metallic</span><span style="color: #A45A77; font-weight: bold">${</span>texture_suffix<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>metallic_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`metallic</span><span style="color: #A45A77; font-weight: bold">${</span>texture_suffix<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>normal_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`normal</span><span style="color: #A45A77; font-weight: bold">${</span>texture_suffix<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>normal_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`normal</span><span style="color: #A45A77; font-weight: bold">${</span>texture_suffix<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>roughness_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`roughness</span><span style="color: #A45A77; font-weight: bold">${</span>texture_suffix<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>roughness_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">`roughness</span><span style="color: #A45A77; font-weight: bold">${</span>texture_suffix<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>filamat_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">&#39;textured.filamat&#39;</span>; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>filamat_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">&#39;textured.filamat&#39;</span>;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>filamesh_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">&#39;suzanne.filamesh&#39;</span>; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>filamesh_url<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #BA2121">&#39;suzanne.filamesh&#39;</span>;<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<h2>Create skybox and IBL</h2> <h2>Create skybox and IBL</h2>
<p>Next, let&#x27;s create the low-resolution skybox and IBL in the <code>App</code> constructor.</p> <p>Next, let&#x27;s create the low-resolution skybox and IBL in the <code>App</code> constructor.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">this</span>.skybox<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createSkyFromKtx1(sky_small_url); <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">this</span>.skybox<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createSkyFromKtx1(sky_small_url);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.scene.setSkybox(<span style="color: #008000; font-weight: bold">this</span>.skybox); <span style="color: #008000; font-weight: bold">this</span>.scene.setSkybox(<span style="color: #008000; font-weight: bold">this</span>.skybox);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.indirectLight<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createIblFromKtx1(ibl_url); <span style="color: #008000; font-weight: bold">this</span>.indirectLight<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createIblFromKtx1(ibl_url);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.indirectLight.setIntensity(<span style="color: #666666">100000</span>); <span style="color: #008000; font-weight: bold">this</span>.indirectLight.setIntensity(<span style="color: #666666">100000</span>);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.scene.setIndirectLight(<span style="color: #008000; font-weight: bold">this</span>.indirectLight); <span style="color: #008000; font-weight: bold">this</span>.scene.setIndirectLight(<span style="color: #008000; font-weight: bold">this</span>.indirectLight);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>This allows users to see a reasonable background fairly quickly, before larger assets have finished <p>This allows users to see a reasonable background fairly quickly, before larger assets have finished
@@ -206,31 +206,31 @@ when the assets have finished downloading.</p>
<p>In our callback, we&#x27;ll make several <code>setTextureParameter</code> calls on the material instance, then we&#x27;ll <p>In our callback, we&#x27;ll make several <code>setTextureParameter</code> calls on the material instance, then we&#x27;ll
recreate the skybox using a higher-resolution texture. As a last step we unhide the renderable that recreate the skybox using a higher-resolution texture. As a last step we unhide the renderable that
was created in the app constructor.</p> was created in the app constructor.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>Filament.fetch([sky_large_url,<span style="color: #bbbbbb"> </span>albedo_url,<span style="color: #bbbbbb"> </span>roughness_url,<span style="color: #bbbbbb"> </span>metallic_url,<span style="color: #bbbbbb"> </span>normal_url,<span style="color: #bbbbbb"> </span>ao_url],<span style="color: #bbbbbb"> </span>()<span style="color: #bbbbbb"> </span>=&gt;<span style="color: #bbbbbb"> </span>{ <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>Filament.fetch([sky_large_url,<span style="color: #bbbbbb"> </span>albedo_url,<span style="color: #bbbbbb"> </span>roughness_url,<span style="color: #bbbbbb"> </span>metallic_url,<span style="color: #bbbbbb"> </span>normal_url,<span style="color: #bbbbbb"> </span>ao_url],<span style="color: #bbbbbb"> </span>()<span style="color: #bbbbbb"> </span>=&gt;<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>albedo<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createTextureFromKtx1(albedo_url,<span style="color: #bbbbbb"> </span>{srgb<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">true</span>}); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>albedo<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createTextureFromKtx1(albedo_url,<span style="color: #bbbbbb"> </span>{srgb<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">true</span>});<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>roughness<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createTextureFromKtx1(roughness_url); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>roughness<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createTextureFromKtx1(roughness_url);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>metallic<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createTextureFromKtx1(metallic_url); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>metallic<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createTextureFromKtx1(metallic_url);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>normal<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createTextureFromKtx1(normal_url); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>normal<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createTextureFromKtx1(normal_url);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>ao<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createTextureFromKtx1(ao_url); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>ao<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createTextureFromKtx1(ao_url);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>sampler<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>Filament.TextureSampler( <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>sampler<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>Filament.TextureSampler(<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>Filament.MinFilter.LINEAR_MIPMAP_LINEAR, <span style="color: #bbbbbb"> </span>Filament.MinFilter.LINEAR_MIPMAP_LINEAR,<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>Filament.MagFilter.LINEAR, <span style="color: #bbbbbb"> </span>Filament.MagFilter.LINEAR,<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>Filament.WrapMode.CLAMP_TO_EDGE); <span style="color: #bbbbbb"> </span>Filament.WrapMode.CLAMP_TO_EDGE);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">&#39;albedo&#39;</span>,<span style="color: #bbbbbb"> </span>albedo,<span style="color: #bbbbbb"> </span>sampler); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">&#39;albedo&#39;</span>,<span style="color: #bbbbbb"> </span>albedo,<span style="color: #bbbbbb"> </span>sampler);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">&#39;roughness&#39;</span>,<span style="color: #bbbbbb"> </span>roughness,<span style="color: #bbbbbb"> </span>sampler); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">&#39;roughness&#39;</span>,<span style="color: #bbbbbb"> </span>roughness,<span style="color: #bbbbbb"> </span>sampler);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">&#39;metallic&#39;</span>,<span style="color: #bbbbbb"> </span>metallic,<span style="color: #bbbbbb"> </span>sampler); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">&#39;metallic&#39;</span>,<span style="color: #bbbbbb"> </span>metallic,<span style="color: #bbbbbb"> </span>sampler);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">&#39;normal&#39;</span>,<span style="color: #bbbbbb"> </span>normal,<span style="color: #bbbbbb"> </span>sampler); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">&#39;normal&#39;</span>,<span style="color: #bbbbbb"> </span>normal,<span style="color: #bbbbbb"> </span>sampler);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">&#39;ao&#39;</span>,<span style="color: #bbbbbb"> </span>ao,<span style="color: #bbbbbb"> </span>sampler); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">&#39;ao&#39;</span>,<span style="color: #bbbbbb"> </span>ao,<span style="color: #bbbbbb"> </span>sampler);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// Replace low-res skybox with high-res skybox.</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// Replace low-res skybox with high-res skybox.</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.destroySkybox(<span style="color: #008000; font-weight: bold">this</span>.skybox); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.destroySkybox(<span style="color: #008000; font-weight: bold">this</span>.skybox);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.skybox<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createSkyFromKtx1(sky_large_url); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.skybox<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.createSkyFromKtx1(sky_large_url);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.scene.setSkybox(<span style="color: #008000; font-weight: bold">this</span>.skybox); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.scene.setSkybox(<span style="color: #008000; font-weight: bold">this</span>.skybox);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.scene.addEntity(<span style="color: #008000; font-weight: bold">this</span>.suzanne); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.scene.addEntity(<span style="color: #008000; font-weight: bold">this</span>.suzanne);<span style="color: #bbbbbb"></span>
}); });<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<h2>Introduce trackball rotation</h2> <h2>Introduce trackball rotation</h2>
@@ -241,13 +241,13 @@ listens for drag events and computes a rotation matrix.</p>
<p>Next, replace the <strong>initialize gltumble</strong> and <strong>apply gltumble matrix</strong> comments with the following <p>Next, replace the <strong>initialize gltumble</strong> and <strong>apply gltumble matrix</strong> comments with the following
two code snippets.</p> two code snippets.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">this</span>.trackball<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>Trackball(canvas,<span style="color: #bbbbbb"> </span>{startSpin<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span><span style="color: #666666">0.035</span>}); <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">this</span>.trackball<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>Trackball(canvas,<span style="color: #bbbbbb"> </span>{startSpin<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span><span style="color: #666666">0.035</span>});<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>tcm<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.getTransformManager(); <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>tcm<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.getTransformManager();<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>inst<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>tcm.getInstance(<span style="color: #008000; font-weight: bold">this</span>.suzanne); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>inst<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>tcm.getInstance(<span style="color: #008000; font-weight: bold">this</span>.suzanne);<span style="color: #bbbbbb"></span>
tcm.setTransform(inst,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.trackball.getMatrix()); tcm.setTransform(inst,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.trackball.getMatrix());<span style="color: #bbbbbb"></span>
inst.<span style="color: #AA22FF; font-weight: bold">delete</span>(); inst.<span style="color: #AA22FF; font-weight: bold">delete</span>();<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>That&#x27;s it, we now have a fast-loading interactive demo. The complete JavaScript file is available <p>That&#x27;s it, we now have a fast-loading interactive demo. The complete JavaScript file is available
+87 -87
View File
@@ -22,9 +22,9 @@ a mobile-friendly page with a full-screen canvas.</p>
&lt;<span style="color: #008000; font-weight: bold">title</span>&gt;Filament Tutorial&lt;/<span style="color: #008000; font-weight: bold">title</span>&gt; &lt;<span style="color: #008000; font-weight: bold">title</span>&gt;Filament Tutorial&lt;/<span style="color: #008000; font-weight: bold">title</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">meta</span> <span style="color: #687822">charset</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;utf-8&quot;</span>&gt; &lt;<span style="color: #008000; font-weight: bold">meta</span> <span style="color: #687822">charset</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;utf-8&quot;</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">meta</span> <span style="color: #687822">name</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;viewport&quot;</span> <span style="color: #687822">content</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;width=device-width,user-scalable=no,initial-scale=1&quot;</span>&gt; &lt;<span style="color: #008000; font-weight: bold">meta</span> <span style="color: #687822">name</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;viewport&quot;</span> <span style="color: #687822">content</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;width=device-width,user-scalable=no,initial-scale=1&quot;</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">style</span>&gt; &lt;<span style="color: #008000; font-weight: bold">style</span>&gt;<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">body</span><span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">margin</span>:<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>;<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">overflow</span>:<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">hidden</span>;<span style="color: #bbbbbb"> </span>} <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">body</span><span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">margin</span>:<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>;<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">overflow</span>:<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">hidden</span>;<span style="color: #bbbbbb"> </span>}<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">canvas</span><span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"> </span>touch-action:<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">none</span>;<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">width</span>:<span style="color: #bbbbbb"> </span><span style="color: #666666">100</span><span style="color: #B00040">%</span>;<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">height</span>:<span style="color: #bbbbbb"> </span><span style="color: #666666">100</span><span style="color: #B00040">%</span>;<span style="color: #bbbbbb"> </span>} <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">canvas</span><span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"> </span>touch-action:<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">none</span>;<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">width</span>:<span style="color: #bbbbbb"> </span><span style="color: #666666">100</span><span style="color: #B00040">%</span>;<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">height</span>:<span style="color: #bbbbbb"> </span><span style="color: #666666">100</span><span style="color: #B00040">%</span>;<span style="color: #bbbbbb"> </span>}<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>&lt;/<span style="color: #008000; font-weight: bold">style</span>&gt; <span style="color: #bbbbbb"> </span>&lt;/<span style="color: #008000; font-weight: bold">style</span>&gt;
&lt;/<span style="color: #008000; font-weight: bold">head</span>&gt; &lt;/<span style="color: #008000; font-weight: bold">head</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">body</span>&gt; &lt;<span style="color: #008000; font-weight: bold">body</span>&gt;
@@ -48,24 +48,24 @@ a mobile-friendly page with a full-screen canvas.</p>
<li><code>triangle.js</code> will contain your application code.</li> <li><code>triangle.js</code> will contain your application code.</li>
</ul> </ul>
<p>Go ahead and create <code>triangle.js</code> with the following content.</p> <p>Go ahead and create <code>triangle.js</code> with the following content.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">class</span><span style="color: #bbbbbb"> </span>App<span style="color: #bbbbbb"> </span>{ <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">class</span><span style="color: #bbbbbb"> </span>App<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">constructor</span>()<span style="color: #bbbbbb"> </span>{ <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">constructor</span>()<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: create entities</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: create entities</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.render<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.render.bind(<span style="color: #008000; font-weight: bold">this</span>); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.render<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.render.bind(<span style="color: #008000; font-weight: bold">this</span>);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize.bind(<span style="color: #008000; font-weight: bold">this</span>); <span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize.bind(<span style="color: #008000; font-weight: bold">this</span>);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.addEventListener(<span style="color: #BA2121">&#39;resize&#39;</span>,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize); <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.addEventListener(<span style="color: #BA2121">&#39;resize&#39;</span>,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.resize);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render); <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>} <span style="color: #bbbbbb"> </span>}<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>render()<span style="color: #bbbbbb"> </span>{ <span style="color: #bbbbbb"> </span>render()<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: render scene</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: render scene</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render); <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>} <span style="color: #bbbbbb"> </span>}<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>resize()<span style="color: #bbbbbb"> </span>{ <span style="color: #bbbbbb"> </span>resize()<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: adjust viewport and canvas</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: adjust viewport and canvas</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>} <span style="color: #bbbbbb"> </span>}<span style="color: #bbbbbb"></span>
} }<span style="color: #bbbbbb"></span>
Filament.init([<span style="color: #BA2121">&#39;triangle.filamat&#39;</span>],<span style="color: #bbbbbb"> </span>()<span style="color: #bbbbbb"> </span>=&gt;<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.app<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>App()<span style="color: #bbbbbb"> </span>}<span style="color: #bbbbbb"> </span>); Filament.init([<span style="color: #BA2121">&#39;triangle.filamat&#39;</span>],<span style="color: #bbbbbb"> </span>()<span style="color: #bbbbbb"> </span>=&gt;<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.app<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span>App()<span style="color: #bbbbbb"> </span>}<span style="color: #bbbbbb"> </span>);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>The two calls to <code>bind()</code> allow us to pass instance methods as callbacks for animation and resize <p>The two calls to <code>bind()</code> allow us to pass instance methods as callbacks for animation and resize
@@ -81,9 +81,9 @@ that define a PBR material. We&#x27;ll learn more about material packages in the
<h2>Spawn a local server</h2> <h2>Spawn a local server</h2>
<p>Because of CORS restrictions, your web app cannot fetch the material package directly from the <p>Because of CORS restrictions, your web app cannot fetch the material package directly from the
file system. One way around this is to create a temporary server using Python or node:</p> file system. One way around this is to create a temporary server using Python or node:</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>python3<span style="color: #bbbbbb"> </span>-m<span style="color: #bbbbbb"> </span>http.server<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic"># Python 3</span> <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>python3 -m http.server <span style="color: #3D7B7B; font-style: italic"># Python 3</span>
python<span style="color: #bbbbbb"> </span>-m<span style="color: #bbbbbb"> </span>SimpleHTTPServer<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic"># Python 2.7</span> python -m SimpleHTTPServer <span style="color: #3D7B7B; font-style: italic"># Python 2.7</span>
npx<span style="color: #bbbbbb"> </span>http-server<span style="color: #bbbbbb"> </span>-p<span style="color: #bbbbbb"> </span><span style="color: #666666">8000</span><span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic"># nodejs</span> npx http-server -p <span style="color: #666666">8000</span> <span style="color: #3D7B7B; font-style: italic"># nodejs</span>
</pre></div> </pre></div>
<p>To see if this works, navigate to <a href="http://localhost:8000">http://localhost:8000</a> and check if you <p>To see if this works, navigate to <a href="http://localhost:8000">http://localhost:8000</a> and check if you
@@ -93,8 +93,8 @@ with the correct MIME type.</p>
<h2>Create the Engine and Scene</h2> <h2>Create the Engine and Scene</h2>
<p>We now have a basic skeleton that can respond to paint and resize events. Let&#x27;s start adding <p>We now have a basic skeleton that can respond to paint and resize events. Let&#x27;s start adding
Filament objects to the app. Insert the following code into the top of the app constructor.</p> Filament objects to the app. Insert the following code into the top of the app constructor.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">this</span>.canvas<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">document</span>.getElementsByTagName(<span style="color: #BA2121">&#39;canvas&#39;</span>)[<span style="color: #666666">0</span>]; <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">this</span>.canvas<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">document</span>.getElementsByTagName(<span style="color: #BA2121">&#39;canvas&#39;</span>)[<span style="color: #666666">0</span>];<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>engine<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Engine.create(<span style="color: #008000; font-weight: bold">this</span>.canvas); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>engine<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Engine.create(<span style="color: #008000; font-weight: bold">this</span>.canvas);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>The above snippet creates the <code>Engine</code> by passing it a canvas DOM object. The engine needs the <p>The above snippet creates the <code>Engine</code> by passing it a canvas DOM object. The engine needs the
@@ -102,9 +102,9 @@ canvas in order to create a WebGL 2.0 context in its contructor.</p>
<p>The engine is a factory for many Filament entities, including <code>Scene</code>, which is a flat container of <p>The engine is a factory for many Filament entities, including <code>Scene</code>, which is a flat container of
entities. Let&#x27;s go ahead and create a scene, then add a blank entity called <code>triangle</code> into the entities. Let&#x27;s go ahead and create a scene, then add a blank entity called <code>triangle</code> into the
scene.</p> scene.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">this</span>.scene<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createScene(); <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">this</span>.scene<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createScene();<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.triangle<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.EntityManager.get().create(); <span style="color: #008000; font-weight: bold">this</span>.triangle<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.EntityManager.get().create();<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.scene.addEntity(<span style="color: #008000; font-weight: bold">this</span>.triangle); <span style="color: #008000; font-weight: bold">this</span>.scene.addEntity(<span style="color: #008000; font-weight: bold">this</span>.triangle);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>Filament uses an <a href="//en.wikipedia.org/wiki/Entity-component-system">Entity-Component System</a>. <p>Filament uses an <a href="//en.wikipedia.org/wiki/Entity-component-system">Entity-Component System</a>.
@@ -114,28 +114,28 @@ calls.</p>
<h2>Construct typed arrays</h2> <h2>Construct typed arrays</h2>
<p>Next we&#x27;ll create two typed arrays: a positions array with XY coordinates for each vertex, and a <p>Next we&#x27;ll create two typed arrays: a positions array with XY coordinates for each vertex, and a
colors array with a 32-bit word for each vertex.</p> colors array with a 32-bit word for each vertex.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>TRIANGLE_POSITIONS<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span><span style="color: #008000">Float32Array</span>([ <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>TRIANGLE_POSITIONS<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span><span style="color: #008000">Float32Array</span>([<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>, <span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">Math</span>.cos(<span style="color: #008000">Math</span>.PI<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span><span style="color: #666666">2</span><span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span><span style="color: #666666">3</span>),<span style="color: #bbbbbb"> </span><span style="color: #008000">Math</span>.sin(<span style="color: #008000">Math</span>.PI<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span><span style="color: #666666">2</span><span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span><span style="color: #666666">3</span>), <span style="color: #bbbbbb"> </span><span style="color: #008000">Math</span>.cos(<span style="color: #008000">Math</span>.PI<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span><span style="color: #666666">2</span><span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span><span style="color: #666666">3</span>),<span style="color: #bbbbbb"> </span><span style="color: #008000">Math</span>.sin(<span style="color: #008000">Math</span>.PI<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span><span style="color: #666666">2</span><span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span><span style="color: #666666">3</span>),<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">Math</span>.cos(<span style="color: #008000">Math</span>.PI<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span><span style="color: #666666">4</span><span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span><span style="color: #666666">3</span>),<span style="color: #bbbbbb"> </span><span style="color: #008000">Math</span>.sin(<span style="color: #008000">Math</span>.PI<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span><span style="color: #666666">4</span><span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span><span style="color: #666666">3</span>), <span style="color: #bbbbbb"> </span><span style="color: #008000">Math</span>.cos(<span style="color: #008000">Math</span>.PI<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span><span style="color: #666666">4</span><span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span><span style="color: #666666">3</span>),<span style="color: #bbbbbb"> </span><span style="color: #008000">Math</span>.sin(<span style="color: #008000">Math</span>.PI<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span><span style="color: #666666">4</span><span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span><span style="color: #666666">3</span>),<span style="color: #bbbbbb"></span>
]); ]);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>TRIANGLE_COLORS<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span><span style="color: #008000">Uint32Array</span>([<span style="color: #666666">0xffff0000</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0xff00ff00</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0xff0000ff</span>]); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>TRIANGLE_COLORS<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span><span style="color: #008000">Uint32Array</span>([<span style="color: #666666">0xffff0000</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0xff00ff00</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0xff0000ff</span>]);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>Next we&#x27;ll use the positions and colors buffers to create a single <code>VertexBuffer</code> object.</p> <p>Next we&#x27;ll use the positions and colors buffers to create a single <code>VertexBuffer</code> object.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>VertexAttribute<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.VertexAttribute; <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>VertexAttribute<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.VertexAttribute;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>AttributeType<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.VertexBuffer$AttributeType; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>AttributeType<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.VertexBuffer$AttributeType;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.vb<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.VertexBuffer.Builder() <span style="color: #008000; font-weight: bold">this</span>.vb<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.VertexBuffer.Builder()<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.vertexCount(<span style="color: #666666">3</span>) <span style="color: #bbbbbb"> </span>.vertexCount(<span style="color: #666666">3</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.bufferCount(<span style="color: #666666">2</span>) <span style="color: #bbbbbb"> </span>.bufferCount(<span style="color: #666666">2</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.attribute(VertexAttribute.POSITION,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>AttributeType.FLOAT2,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">8</span>) <span style="color: #bbbbbb"> </span>.attribute(VertexAttribute.POSITION,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>AttributeType.FLOAT2,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">8</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.attribute(VertexAttribute.COLOR,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span>AttributeType.UBYTE4,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">4</span>) <span style="color: #bbbbbb"> </span>.attribute(VertexAttribute.COLOR,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span>AttributeType.UBYTE4,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">4</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.normalized(VertexAttribute.COLOR) <span style="color: #bbbbbb"> </span>.normalized(VertexAttribute.COLOR)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.build(engine); <span style="color: #bbbbbb"> </span>.build(engine);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.vb.setBufferAt(engine,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>TRIANGLE_POSITIONS); <span style="color: #008000; font-weight: bold">this</span>.vb.setBufferAt(engine,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>TRIANGLE_POSITIONS);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.vb.setBufferAt(engine,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span>TRIANGLE_COLORS); <span style="color: #008000; font-weight: bold">this</span>.vb.setBufferAt(engine,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span>TRIANGLE_COLORS);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>The above snippet first creates aliases for two enum types, then constructs the vertex buffer using <p>The above snippet first creates aliases for two enum types, then constructs the vertex buffer using
@@ -149,12 +149,12 @@ attribute. Alternatively, we could have interleaved or concatenated these attrib
buffer slot.</p> buffer slot.</p>
<p>Next we&#x27;ll construct an index buffer. The index buffer for our triangle is trivial: it simply holds <p>Next we&#x27;ll construct an index buffer. The index buffer for our triangle is trivial: it simply holds
the integers 0,1,2.</p> the integers 0,1,2.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">this</span>.ib<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.IndexBuffer.Builder() <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">this</span>.ib<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.IndexBuffer.Builder()<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.indexCount(<span style="color: #666666">3</span>) <span style="color: #bbbbbb"> </span>.indexCount(<span style="color: #666666">3</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.bufferType(Filament.IndexBuffer$IndexType.USHORT) <span style="color: #bbbbbb"> </span>.bufferType(Filament.IndexBuffer$IndexType.USHORT)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.build(engine); <span style="color: #bbbbbb"> </span>.build(engine);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.ib.setBuffer(engine,<span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span><span style="color: #008000">Uint16Array</span>([<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">2</span>])); <span style="color: #008000; font-weight: bold">this</span>.ib.setBuffer(engine,<span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">new</span><span style="color: #bbbbbb"> </span><span style="color: #008000">Uint16Array</span>([<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">2</span>]));<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>Note that constructing an index buffer is similar to constructing a vertex buffer, but it only has <p>Note that constructing an index buffer is similar to constructing a vertex buffer, but it only has
@@ -167,29 +167,29 @@ parameters, and they can be bound to renderables. We&#x27;ll learn more about ma
next tutorial.</p> next tutorial.</p>
<p>After extracting the material instance, we can finally create a renderable component for the <p>After extracting the material instance, we can finally create a renderable component for the
triangle by setting up a bounding box and passing in the vertex and index buffers.</p> triangle by setting up a bounding box and passing in the vertex and index buffers.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>mat<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createMaterial(<span style="color: #BA2121">&#39;triangle.filamat&#39;</span>); <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>mat<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createMaterial(<span style="color: #BA2121">&#39;triangle.filamat&#39;</span>);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>matinst<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>mat.getDefaultInstance(); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>matinst<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>mat.getDefaultInstance();<span style="color: #bbbbbb"></span>
Filament.RenderableManager.Builder(<span style="color: #666666">1</span>) Filament.RenderableManager.Builder(<span style="color: #666666">1</span>)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.boundingBox({<span style="color: #bbbbbb"> </span>center<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">-1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">-1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">-1</span>],<span style="color: #bbbbbb"> </span>halfExtent<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>]<span style="color: #bbbbbb"> </span>}) <span style="color: #bbbbbb"> </span>.boundingBox({<span style="color: #bbbbbb"> </span>center<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">-1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">-1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">-1</span>],<span style="color: #bbbbbb"> </span>halfExtent<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>]<span style="color: #bbbbbb"> </span>})<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.material(<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>matinst) <span style="color: #bbbbbb"> </span>.material(<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>matinst)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.geometry(<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>Filament.RenderableManager$PrimitiveType.TRIANGLES,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.vb,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.ib) <span style="color: #bbbbbb"> </span>.geometry(<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>Filament.RenderableManager$PrimitiveType.TRIANGLES,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.vb,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.ib)<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span>.build(engine,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.triangle); <span style="color: #bbbbbb"> </span>.build(engine,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.triangle);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>Next let&#x27;s wrap up the initialization routine by creating the swap chain, renderer, camera, and <p>Next let&#x27;s wrap up the initialization routine by creating the swap chain, renderer, camera, and
view.</p> view.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">this</span>.swapChain<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createSwapChain(); <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">this</span>.swapChain<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createSwapChain();<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.renderer<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createRenderer(); <span style="color: #008000; font-weight: bold">this</span>.renderer<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createRenderer();<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.camera<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createCamera(Filament.EntityManager.get().create()); <span style="color: #008000; font-weight: bold">this</span>.camera<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createCamera(Filament.EntityManager.get().create());<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.view<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createView(); <span style="color: #008000; font-weight: bold">this</span>.view<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>engine.createView();<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.view.setCamera(<span style="color: #008000; font-weight: bold">this</span>.camera); <span style="color: #008000; font-weight: bold">this</span>.view.setCamera(<span style="color: #008000; font-weight: bold">this</span>.camera);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.view.setScene(<span style="color: #008000; font-weight: bold">this</span>.scene); <span style="color: #008000; font-weight: bold">this</span>.view.setScene(<span style="color: #008000; font-weight: bold">this</span>.scene);<span style="color: #bbbbbb"></span>
<span style="color: #3D7B7B; font-style: italic">// Set up a blue-green background:</span> <span style="color: #3D7B7B; font-style: italic">// Set up a blue-green background:</span><span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.renderer.setClearOptions({clearColor<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0.0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.2</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1.0</span>],<span style="color: #bbbbbb"> </span>clear<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">true</span>}); <span style="color: #008000; font-weight: bold">this</span>.renderer.setClearOptions({clearColor<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span>[<span style="color: #666666">0.0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0.2</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1.0</span>],<span style="color: #bbbbbb"> </span>clear<span style="color: #666666">:</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">true</span>});<span style="color: #bbbbbb"></span>
<span style="color: #3D7B7B; font-style: italic">// Adjust the initial viewport:</span> <span style="color: #3D7B7B; font-style: italic">// Adjust the initial viewport:</span><span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.resize(); <span style="color: #008000; font-weight: bold">this</span>.resize();<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>At this point, we&#x27;re done creating all Filament entities, and the code should run without errors. <p>At this point, we&#x27;re done creating all Filament entities, and the code should run without errors.
@@ -197,24 +197,24 @@ However the canvas is still blank!</p>
<h2>Render and resize handlers</h2> <h2>Render and resize handlers</h2>
<p>Recall that our App class has a skeletal render method, which the browser calls every time it needs <p>Recall that our App class has a skeletal render method, which the browser calls every time it needs
to repaint. Often this is 60 times a second.</p> to repaint. Often this is 60 times a second.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>render()<span style="color: #bbbbbb"> </span>{ <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>render()<span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: render scene</span> <span style="color: #bbbbbb"> </span><span style="color: #3D7B7B; font-style: italic">// TODO: render scene</span><span style="color: #bbbbbb"></span>
<span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render); <span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);<span style="color: #bbbbbb"></span>
} }<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>Let&#x27;s flesh this out by rotating the triangle and invoking the Filament renderer. Add the following <p>Let&#x27;s flesh this out by rotating the triangle and invoking the Filament renderer. Add the following
code to the top of the render method.</p> code to the top of the render method.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #3D7B7B; font-style: italic">// Rotate the triangle.</span> <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #3D7B7B; font-style: italic">// Rotate the triangle.</span><span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>radians<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">Date</span>.now()<span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span><span style="color: #666666">1000</span>; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>radians<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">Date</span>.now()<span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span><span style="color: #666666">1000</span>;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>transform<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>mat4.fromRotation(mat4.create(),<span style="color: #bbbbbb"> </span>radians,<span style="color: #bbbbbb"> </span>[<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>]); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>transform<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>mat4.fromRotation(mat4.create(),<span style="color: #bbbbbb"> </span>radians,<span style="color: #bbbbbb"> </span>[<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>]);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>tcm<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.getTransformManager(); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>tcm<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.engine.getTransformManager();<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>inst<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>tcm.getInstance(<span style="color: #008000; font-weight: bold">this</span>.triangle); <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>inst<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>tcm.getInstance(<span style="color: #008000; font-weight: bold">this</span>.triangle);<span style="color: #bbbbbb"></span>
tcm.setTransform(inst,<span style="color: #bbbbbb"> </span>transform); tcm.setTransform(inst,<span style="color: #bbbbbb"> </span>transform);<span style="color: #bbbbbb"></span>
inst.<span style="color: #AA22FF; font-weight: bold">delete</span>(); inst.<span style="color: #AA22FF; font-weight: bold">delete</span>();<span style="color: #bbbbbb"></span>
<span style="color: #3D7B7B; font-style: italic">// Render the frame.</span> <span style="color: #3D7B7B; font-style: italic">// Render the frame.</span><span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.renderer.render(<span style="color: #008000; font-weight: bold">this</span>.swapChain,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view); <span style="color: #008000; font-weight: bold">this</span>.renderer.render(<span style="color: #008000; font-weight: bold">this</span>.swapChain,<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.view);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>The first half of our render method obtains the transform component of the triangle entity and uses <p>The first half of our render method obtains the transform component of the triangle entity and uses
@@ -225,14 +225,14 @@ that it wants to skip a frame, hence the <code>if</code> statement.</p>
<p>One last step. Add the following code to the resize method. This adjusts the resolution of the <p>One last step. Add the following code to the resize method. This adjusts the resolution of the
rendering surface when the window size changes, taking <code>devicePixelRatio</code> into account for high-DPI rendering surface when the window size changes, taking <code>devicePixelRatio</code> into account for high-DPI
displays. It also adjusts the camera frustum accordingly.</p> displays. It also adjusts the camera frustum accordingly.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>dpr<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.devicePixelRatio; <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>dpr<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.devicePixelRatio;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>width<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas.width<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.innerWidth<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span>dpr; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>width<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas.width<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.innerWidth<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span>dpr;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>height<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas.height<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.innerHeight<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span>dpr; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>height<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">this</span>.canvas.height<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #008000">window</span>.innerHeight<span style="color: #bbbbbb"> </span><span style="color: #666666">*</span><span style="color: #bbbbbb"> </span>dpr;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.view.setViewport([<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>width,<span style="color: #bbbbbb"> </span>height]); <span style="color: #008000; font-weight: bold">this</span>.view.setViewport([<span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span>width,<span style="color: #bbbbbb"> </span>height]);<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>aspect<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>width<span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span>height; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>aspect<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>width<span style="color: #bbbbbb"> </span><span style="color: #666666">/</span><span style="color: #bbbbbb"> </span>height;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>Projection<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Camera$Projection; <span style="color: #008000; font-weight: bold">const</span><span style="color: #bbbbbb"> </span>Projection<span style="color: #bbbbbb"> </span><span style="color: #666666">=</span><span style="color: #bbbbbb"> </span>Filament.Camera$Projection;<span style="color: #bbbbbb"></span>
<span style="color: #008000; font-weight: bold">this</span>.camera.setProjection(Projection.ORTHO,<span style="color: #bbbbbb"> </span><span style="color: #666666">-</span>aspect,<span style="color: #bbbbbb"> </span>aspect,<span style="color: #bbbbbb"> </span><span style="color: #666666">-1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>); <span style="color: #008000; font-weight: bold">this</span>.camera.setProjection(Projection.ORTHO,<span style="color: #bbbbbb"> </span><span style="color: #666666">-</span>aspect,<span style="color: #bbbbbb"> </span>aspect,<span style="color: #bbbbbb"> </span><span style="color: #666666">-1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>,<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span>);<span style="color: #bbbbbb"></span>
</pre></div> </pre></div>
<p>You should now have a spinning triangle! The completed JavaScript is available <p>You should now have a spinning triangle! The completed JavaScript is available
+32 -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
@@ -233,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})
@@ -311,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(
@@ -375,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
@@ -386,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
@@ -436,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
+21 -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)
@@ -157,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
@@ -166,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
@@ -181,32 +190,26 @@ if (FILAMENT_SUPPORTS_VULKAN)
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()
@@ -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
+57 -22
View File
@@ -106,7 +106,8 @@ static constexpr size_t CONFIG_SAMPLER_BINDING_COUNT = 4; // This is guarantee
* Defines the backend's feature levels. * Defines the backend's feature levels.
*/ */
enum class FeatureLevel : uint8_t { enum class FeatureLevel : uint8_t {
FEATURE_LEVEL_1 = 1, //!< OpenGL ES 3.0 features (default) FEATURE_LEVEL_0 = 0, //!< OpenGL ES 2.0 features
FEATURE_LEVEL_1, //!< OpenGL ES 3.0 features (default)
FEATURE_LEVEL_2, //!< OpenGL ES 3.1 features + 16 textures units + cubemap arrays FEATURE_LEVEL_2, //!< OpenGL ES 3.1 features + 16 textures units + cubemap arrays
FEATURE_LEVEL_3 //!< OpenGL ES 3.1 features + 31 textures units + cubemap arrays FEATURE_LEVEL_3 //!< OpenGL ES 3.1 features + 31 textures units + cubemap arrays
}; };
@@ -295,6 +296,14 @@ enum class Precision : uint8_t {
DEFAULT DEFAULT
}; };
/**
* Shader compiler priority queue
*/
enum class CompilerPriorityQueue : uint8_t {
HIGH,
LOW
};
//! Texture sampler type //! Texture sampler type
enum class SamplerType : uint8_t { enum class SamplerType : uint8_t {
SAMPLER_2D, //!< 2D texture SAMPLER_2D, //!< 2D texture
@@ -787,32 +796,53 @@ enum class SamplerCompareFunc : uint8_t {
//! Sampler parameters //! Sampler parameters
struct SamplerParams { // NOLINT struct SamplerParams { // NOLINT
union { SamplerMagFilter filterMag : 1; //!< magnification filter (NEAREST)
struct { SamplerMinFilter filterMin : 3; //!< minification filter (NEAREST)
SamplerMagFilter filterMag : 1; //!< magnification filter (NEAREST) SamplerWrapMode wrapS : 2; //!< s-coordinate wrap mode (CLAMP_TO_EDGE)
SamplerMinFilter filterMin : 3; //!< minification filter (NEAREST) SamplerWrapMode wrapT : 2; //!< t-coordinate wrap mode (CLAMP_TO_EDGE)
SamplerWrapMode wrapS : 2; //!< s-coordinate wrap mode (CLAMP_TO_EDGE)
SamplerWrapMode wrapT : 2; //!< t-coordinate wrap mode (CLAMP_TO_EDGE)
SamplerWrapMode wrapR : 2; //!< r-coordinate wrap mode (CLAMP_TO_EDGE) SamplerWrapMode wrapR : 2; //!< r-coordinate wrap mode (CLAMP_TO_EDGE)
uint8_t anisotropyLog2 : 3; //!< anisotropy level (0) uint8_t anisotropyLog2 : 3; //!< anisotropy level (0)
SamplerCompareMode compareMode : 1; //!< sampler compare mode (NONE) SamplerCompareMode compareMode : 1; //!< sampler compare mode (NONE)
uint8_t padding0 : 2; //!< reserved. must be 0. uint8_t padding0 : 2; //!< reserved. must be 0.
SamplerCompareFunc compareFunc : 3; //!< sampler comparison function (LE) SamplerCompareFunc compareFunc : 3; //!< sampler comparison function (LE)
uint8_t padding1 : 5; //!< reserved. must be 0. uint8_t padding1 : 5; //!< reserved. must be 0.
uint8_t padding2 : 8; //!< reserved. must be 0.
uint8_t padding2 : 8; //!< reserved. must be 0. struct Hasher {
}; size_t operator()(SamplerParams p) const noexcept {
uint32_t u; // we don't use std::hash<> here, so we don't have to include <functional>
return *reinterpret_cast<uint64_t const*>(reinterpret_cast<char const*>(&p));
}
}; };
struct EqualTo {
bool operator()(SamplerParams lhs, SamplerParams rhs) const noexcept {
auto* pLhs = reinterpret_cast<uint64_t const*>(reinterpret_cast<char const*>(&lhs));
auto* pRhs = reinterpret_cast<uint64_t const*>(reinterpret_cast<char const*>(&rhs));
return *pLhs == *pRhs;
}
};
struct LessThan {
bool operator()(SamplerParams lhs, SamplerParams rhs) const noexcept {
auto* pLhs = reinterpret_cast<uint64_t const*>(reinterpret_cast<char const*>(&lhs));
auto* pRhs = reinterpret_cast<uint64_t const*>(reinterpret_cast<char const*>(&rhs));
return *pLhs == *pRhs;
}
};
private: private:
friend inline bool operator < (SamplerParams lhs, SamplerParams rhs) { friend inline bool operator < (SamplerParams lhs, SamplerParams rhs) noexcept {
return lhs.u < rhs.u; return SamplerParams::LessThan{}(lhs, rhs);
} }
}; };
static_assert(sizeof(SamplerParams) == sizeof(uint32_t), "SamplerParams must be 32 bits"); // The limitation to 64-bits max comes from how we store a SamplerParams in our JNI code
// see android/.../TextureSampler.cpp
static_assert(sizeof(SamplerParams) <= sizeof(uint64_t),
"SamplerParams must be no more than 64 bits");
//! blending equation function //! blending equation function
enum class BlendEquation : uint8_t { enum class BlendEquation : uint8_t {
@@ -1117,8 +1147,6 @@ static_assert(sizeof(StencilState) == 12u,
using FrameScheduledCallback = void(*)(PresentCallable callable, void* user); using FrameScheduledCallback = void(*)(PresentCallable callable, void* user);
using FrameCompletedCallback = void(*)(void* user);
enum class Workaround : uint16_t { enum class Workaround : uint16_t {
// The EASU pass must split because shader compiler flattens early-exit branch // The EASU pass must split because shader compiler flattens early-exit branch
SPLIT_EASU, SPLIT_EASU,
@@ -1129,7 +1157,14 @@ enum class Workaround : uint16_t {
ADRENO_UNIFORM_ARRAY_CRASH, ADRENO_UNIFORM_ARRAY_CRASH,
// Workaround a Metal pipeline compilation error with the message: // Workaround a Metal pipeline compilation error with the message:
// "Could not statically determine the target of a texture". See light_indirect.fs // "Could not statically determine the target of a texture". See light_indirect.fs
A8X_STATIC_TEXTURE_TARGET_ERROR A8X_STATIC_TEXTURE_TARGET_ERROR,
// Adreno drivers sometimes aren't able to blit into a layer of a texture array.
DISABLE_BLIT_INTO_TEXTURE_ARRAY,
// Multiple workarounds needed for PowerVR GPUs
POWER_VR_SHADER_WORKAROUNDS,
// The driver has some threads pinned, and we can't easily know on which core, it can hurt
// performance more if we end-up pinned on the same one.
DISABLE_THREAD_AFFINITY
}; };
} // namespace filament::backend } // namespace filament::backend

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