Compare commits

...
Author SHA1 Message Date
Benjamin Doherty 791f51dcb4 Update glslang to e3bca2a 2022-05-04 12:29:21 -07:00
Benjamin Doherty 4621f3ec5d Filament specific changes 2022-05-04 12:06:26 -07:00
Benjamin Doherty ab9c09d0d9 Update spirv-tools to 46492aa 2022-05-04 12:00:04 -07:00
Benjamin Doherty dbf51c1c7d Update SPIRV-Cross to 0c8a79b 2022-05-04 11:07:15 -07:00
Mathias Agopian ebd5f150c1 fix a potential threading/memory corruption
We can't call prepareProgram() from any thread, since it is calling
into the backend. When we had more than a certain number of commands,
we would use the jobsystem to generate them and so prepareProgram()
could end up being called from a jobsystem thread.

This is fixed by looping through all the commands once they're generated
and calling prepareProgram() then.
2022-05-03 15:16:11 -07:00
Philip Rideout 156dcb54e8 gltf_viewer: fix accidental removal of camera selector. 2022-05-03 14:33:43 -07:00
Mathias Agopian 88ef76989c Cleanup Renderer.cpp
The main changes are:

- ColorPass() and RefractionPass() are now static and moved into a 
  new RendererUtils file. These methods don't need FRenderer and are 
  more like a big "script".

- Cleaned-up includes

- Reformatted/reordered methods
2022-05-03 14:27:48 -07:00
Philip Rideout fc284af684 Rename SimpleViewer to ViewerGui.
The SimpleViewer C++ class was not viewer component like `ModelViewer`
and `<filament-viewer>`. It was actually just the UI builder used
in the `gltf_viewer` desktop app and the remote Android interface.
2022-05-03 08:10:53 -07:00
Philip Rideout 3a8685cd15 Upgrade emsdk to 3.1.9 2022-05-03 08:10:26 -07:00
Philip Rideout f035655f5b Add support for KHR_texture_basisu.
This adds a new implementation of the TextureProvider interface called
Ktx2Provider.

Tested using the KTX2 variant of the StainedGlassLamp model in the
Khronos samples repo.

Tested on WebGL 2.0 (Chrome v100), Android (Pixel 6 Pro), and Desktop
(Metal, OpenGL, and Vulkan via MoltenVK).
2022-05-02 13:15:56 -07:00
Ben Doherty f498e08d1e Update hello-pbr to work in all orientations (#5488) 2022-05-02 14:41:32 -04:00
Philip Rideout db3186a65f Remove etc2comp and astcenc from the repo. 2022-05-02 11:29:19 -07:00
Philip Rideout 248815a3e0 Fix regression with <filament-viewer>. 2022-05-02 11:09:26 -07:00
Benjamin Doherty ebb62b5d55 Release Filament 1.21.3 2022-05-02 13:17:33 -04:00
Philip Rideout b9a5ad205a Fix unit test failures.
Basis does not support DXT3 so in the past this unit test passed only
due to the enum translation bug that was recently fixed.
2022-05-02 09:48:36 -07:00
Philip Rideout 100986d8d9 Fix WebGL debug build (assert with 3-channel images) 2022-04-29 16:30:14 -07:00
Philip Rideout b7c9a36d57 Ktx2Reader: Fix error in enum translation table.
This caused DXT5 content to be interpreted as DXT3 by the GPU,
which seemed to manifest as visual artifacts in the alpha channel.
2022-04-29 16:29:53 -07:00
Philip Rideout d76551ab28 Add async interface to Ktx2Reader. 2022-04-29 14:20:57 -07:00
Mathias Agopian 92bc0752d1 repair VSM gaussian blur
When there was more than one shadowmap we would hit an assert. This 
bug was introduced recently and was due to incorrect use of the 
framegraph.
2022-04-29 12:46:37 -07:00
Mathias Agopian 657c251463 Ensure we always have 4 "safe" mip levels
A "safe" mip-level is one that has exactly half the dimensions of
the current level. In other words, we guarantee that we can halve the
dimensions 4 times without loss (i.e. odd dimension).

This is achieved by effectively padding the viewport (i.e. making the
viewport's dimensions multiple of 16). The post-processing passes
eventually take care of cropping the extra padding so the final
image is unchanged.

This is a more generic solution to dynamic resolution padding, helps
with memory allocations and helps all the algorithms that depend on
mipmaping (e.g. DoF, SSAO, Bloom).


One important improvement brought by this change is that all "final"
post-processing effects are now able to handle a sub-region of the
source, including: color-gradding, fxaa and upscaling.
2022-04-29 12:05:08 -07:00
Philip Rideout b6b8fee483 WebGL: fix isTextureFormatSupported for ETC2 formats.
It was assumed that ETC2 is supported on all ES3 devices, but WebGL on
desktop machines does not support ETC2.

Note that WebGL has its own special extension strings for compressed
textures.
2022-04-29 12:04:59 -07:00
Mathias Agopian be5b60f895 cleaner handling of shadow related uniforms
Some uniforms are needed during shadow map generation, other
during shadow sampling (color pass). We didn't have a clear separation
between them and ended up setting the UBOs that were needed only for
sampling multiple times during generation.
2022-04-29 12:04:47 -07:00
Mathias Agopian 681d31758f move the ShadowUib out of View into ShadowMapManager 2022-04-29 12:04:47 -07:00
Ben Doherty 80dc2f5c9d Move toCompressedFilamentEnum to Ktx1Reader header (#5493) 2022-04-29 14:49:54 -04:00
Mathias Agopian ce7dd7a1fb reorganize again our main UBO
- try to sort data by usage.
- clarify what post-process materials have access to (not enforced yet)
2022-04-28 10:13:20 -07:00
Mathias Agopian 85617c96a2 shrink post-process materials a bit
post-process materials don't need common_shadowing nor common_shading.

also don't rely on MIN_ROUGHNESS in .mat files, because it's not public.
2022-04-28 10:13:20 -07:00
Mathias Agopian 58760adb6a fix typo introduced in previous PR. fixes froxels. 2022-04-27 17:28:16 -07:00
Mathias Agopian 4ef0b72773 rearrange the per-view UBO (breaks materials)
- rename common_math and common_shadowing from .fs to .glsl
  because they were both included in both vertex and fragment
  shaders

- add getFragCoord() which always returns coordinates in the
  glsl convention. This is useful when used with RNGs to get
  consistant results accross backends.
2022-04-27 15:27:47 -07:00
Mathias Agopian 45631c3b81 update binding points from 8 to 12. 2022-04-27 15:27:03 -07:00
Mathias Agopian 6f6dde2579 Optimize custom rendertargets use in Renderer
we just store the "sampleable" attachments as a bitmask in 
RenderTarget instead of computing it each time.
2022-04-27 15:26:45 -07:00
Mathias Agopian e0acbe42cf update material version 2022-04-27 10:14:38 -07:00
Mathias Agopian 4f137ccf89 don't rely on frameUniform.resolution for froxelization
this is because this uniform is not well defined -- it's unclear if
it is set to the viewport or the buffer size.

also, it's not needed, and removes a couple multiplies from the shader.
2022-04-27 09:38:33 -07:00
Mathias Agopian 04010e7dd9 when matdbg is used don't terminate the program on errors 2022-04-27 08:20:00 -07:00
Mathias Agopian f4f9f331c0 CameraInfo cleanups
- add getUserViewMatrix() on CameraInfo, the "user" view matrix is the 
view matrix before we apply the world origin transform, it is needed in
 a few places, so we make it a  method so that in the future we could 
precompute it if we wanted to.

- remove worldOffset which is just the last column of worldOrigin
2022-04-26 11:32:41 -07:00
Mathias Agopian dada291f6b rename mScaling to mScalingCS 2022-04-26 11:32:41 -07:00
Mathias Agopian 18f2f8b6d4 remove unused parameters and state 2022-04-26 11:32:41 -07:00
Mathias Agopian d4117ac968 use interleavedGradientNoise() instead of custom implementaion
interleavedGradientNoise() is available in common_math, so use that
instead of our custom gradient noise RNG.
2022-04-26 11:32:41 -07:00
Mathias Agopian eccbc8c242 simplify FXAA setup
We now do all the setup math on the CPU side, but we also remove some
unnecessary computations based on assumptions that are no longer true.
2022-04-26 11:32:41 -07:00
Mathias Agopian 3cdf24f515 remove getUV() from post-process materials
it made it actually more confusing to have two version of the uv
(normalized and not). Also the unnormalized version was computed from
frameUniforms which is not great in the case of post-processing
(it just happened to work).
2022-04-26 11:30:35 -07:00
Mathias Agopian d91faf9df8 avoid unnecessary parameter copies 2022-04-26 11:28:36 -07:00
Brian Stringham d950efa6ea Changed ALL_SHADER_STATE_FLAGS initializer to support c++17, which is required for C++/CLI support. (#5465) 2022-04-26 08:59:44 -07:00
Benjamin Doherty 861d69ea7c Release Filament 1.21.2 2022-04-25 16:57:00 -04:00
LaiJF b2cc904fab Fix typo 2022-04-25 09:06:12 -07:00
Mathias Agopian 3f87b520bb ShadowMap::render() doesn't need CameraInfo anymore 2022-04-22 12:35:00 -07:00
LaiJF 135a362176 Fix typo (#5455) 2022-04-22 10:46:04 -04:00
Philip Rideout 391ebc3702 gltfio: fix progress indicator when error occurs.
The progress bar in `gltf_viewer` should not appear to hang if any
of an asset's textures fail to load.
2022-04-21 17:41:32 -07:00
Philip Rideout b4d1443720 Repair iOS build. I think. 2022-04-21 15:36:37 -07:00
Philip Rideout c06737aca2 TextureProvider fixup in ResourceLoader JNI. 2022-04-21 13:44:44 -07:00
Philip Rideout f847232296 gltfio: introduce TextureProvider API.
This allows clients to provide their own asynchronous texture decoders
for various mime-typed images. This is a plug-in component for gltfio,
in some ways similar to MaterialProvider.

There are two motivations for this: to decouple gltfio from STB and
to make it easier to integrate support for BasisU textures.

This also has the side effect of simplifying ResourceLoader, since the
texture decoding jobs have been moved out.

As part of this work, I made the "stb" CMake target into a traditional
static library. Previously we had several files called `Image.cpp`
whose sole purpose was to enable STB_IMAGE_IMPLEMENTATION.
2022-04-21 13:25:40 -07:00
LaiJF 89f06b8923 Fix typo (#5454) 2022-04-21 09:52:04 -06:00
Philip Rideout 90a2b1f3c9 Remove WebGL workaround for bloom.
Bloom now works fine (tested with Chrome 100 on a x86 MacBook) without
this workaround for overly aggressive feedback loop detection.
2022-04-20 12:07:49 -07:00
Ben Doherty 059f51338d Audit backends and test cases for correct Y orientation. (#5440) 2022-04-20 11:01:31 -06:00
LaiJF d3cea5121e Fix typo 2022-04-20 09:58:46 -07:00
LaiJF c37301d2dc Fix typo. 2022-04-19 20:27:52 -07:00
Mathias Agopian aa16778fbd don't leak Engine if the driver fail to initialize
If there is an error during the driver initialization, Engine::create() 
returns nullptr, but the FEngine was allocated and would then never
be destroyed.

mTerminated was useless because by construction it would always have
the expected value.
2022-04-19 11:49:07 -07:00
Mathias Agopian ee499ad2ca don't use a unique_ptr to hold the DFG
we can simply make it a member of FEngine.
2022-04-19 11:49:07 -07:00
Mathias Agopian 958dd5bb27 a lot of our workaround don't apply when using ANGLE 2022-04-18 20:19:09 -07:00
Mathias Agopian f988b75999 fix the 2 passes version of FSR
This version is used only on qualcomm devices. It's now forbidden to
create a program inside a renderpass. Unfortunately there was still
one codepath doing so.
2022-04-18 20:18:45 -07:00
Philip Rideout e3ccb4bb3c gltfio Animator: add resetBoneMatrices().
See #5436.
2022-04-18 15:07:35 -07:00
Philip Rideout 3f0dc6f7e6 Minor Ktx2Reader refactoring. 2022-04-18 15:02:08 -07:00
Mathias Agopian c212dd5bc7 remove the CameraInfo state from FView
this state only exists during Renderer::render(), having it outside
of view is more flexible as it give us an opportunity to adjust
camera parameter globally before drawing.

Also greatly reduced the size of RenderPass (which is a Value object).
2022-04-18 12:04:18 -07:00
LaiJF 1eceab0040 Fix typo. 2022-04-18 10:46:31 -07:00
Philip Rideout ab9d1e5956 Fix unit test. 2022-04-15 12:22:12 -07:00
Philip Rideout c906290416 Add to release notes. 2022-04-15 10:54:27 -07:00
Philip Rideout d52a24b6e9 Incorporate feedback from code review. 2022-04-15 10:48:48 -07:00
Philip Rideout 9aeec3a759 Add Ktx2Reader and BasisEncoder and use them in samples.
mipgen can now emit basis-encoded KTX2 files. Both the desktop and
web "suzanne" samples use this as a test for compressed textures.

This PR does not add KTX2 support to glTF, but it's on the way.

`BasisEncoder` has a builder style API that calls the basis encoder to
create KTX2 files. This hides some low-level BasisU features that we are
not using, like file I/O and mipmap generation.

`Ktx2Reader` is an easy-to-use API for creating Filament textures from
KTX2 files. Its API primarily consists of these two methods:

    bool requestFormat(Texture::InternalFormat format);
    Filament::Texture* load(const uint8_t* data, size_t size);

The first method is used to build an ordered list of formats that are
supported by your hardware. The second method consumes the contents of a
basis-encoded KTX2 file and attempts to produce a Filament texture with
a preferred format.

IMPORTANT: Our tools still let you use KTX1 for non-compressed images
because it is useful for HDR, but you can no longer use KTX1 for
block-compressed data.

Partial fix for #4771.
2022-04-15 10:48:48 -07:00
Mathias Agopian 550fcfe2e3 fix typos 2022-04-15 09:18:06 -07:00
Mathias Agopian b2cdf9f2b4 don't issue a flush systematically after framegraph's execute
This is only a good place for a flush *if* we're going to draw another
view (so the GPU can start working). Otherwise, it can be costly
on some drivers and unnecessary since swapbuffers will do the same.
2022-04-15 09:12:39 -07:00
Mathias Agopian 19a3fe3dce allow radius parameter for upsample bloom stage
The original article we used for our bloom (siggraph'14) called for
a radius parameter for the upsample stage. We're always using 1.0 right
now, but it is useful to keep this possibility for experimentations.
2022-04-14 14:04:32 -07:00
Mathias Agopian 754abbf78e bloom pass cleanups 2022-04-14 14:04:32 -07:00
Mathias Agopian 9b855e9a03 fix bloom downsample
a bug was introduced in 8/2020 where the downsampling filter was wrong,
due to a mistake using textureLodOffset, which obviously uses offsets
in source texel -- we were assuming destination.
2022-04-14 14:04:32 -07:00
Mathias Agopian 2534fdf92d propagate the matdbg flag to graddle 2022-04-14 14:04:15 -07:00
Mathias Agopian dab02e915e Remove deprecated Stream APIs 2022-04-14 12:51:03 -07:00
Mathias Agopian 68da1a25eb disable ANGLE optimization that hurts filament 2022-04-14 08:52:56 -07:00
Romain Guy c67b363576 Fix compilation warnings 2022-04-13 15:15:16 -07:00
Philip Rideout 5c0e7d8211 sample-gltf-viewer: fix regression with zip files.
Path resolution was broken with #5285, which only worked when the glTF
happened to be at root level. This new fix has been tested against:

- My Sponza zip file that hass all files in a "sponza" folder.
- My Bistro zip file, which has resources in a child folder relative to
  the gltf file
- A self-created flat zip using IridescentDishWithOlives, with
  everything at root level.

Side note: Bistro still fails on a Pixel 6 Pro Mali but for an unrelated
reason: (null deref in backend::TimerQueryNative::queryResultAvailable)
2022-04-13 12:18:47 -07:00
Benjamin Doherty 3d57c60840 Release Filament 1.21.1 2022-04-13 10:14:44 -06:00
Mathias Agopian 8ab2725a79 string improvements
- don't use __PRETTY_FUNCTION__ and try to parse it, __func__ is
standardized and in most case returns what we want (the function name).

- add native support for string_view in our ostream.

- uninline string support from ostream
2022-04-13 08:53:33 -07:00
Mathias Agopian ff27f8109c Use DEBUG_MARKER() only on (and on all) driver APIs 2022-04-13 08:53:14 -07:00
Philip Rideout 8e09d8bd71 Fix sRGB correctness in Ktx1Reader.
When creating a KTX file (e.g. with mipgen), you can of course choose
whether or not you want to use an sRGB format.

At load time, your app has an expectation about whether a particular
texture has an sRGB format. e.g. the glTF convention is that albedo
textures should be sRGB, while roughness textures are linear.

Before this commit, our KTX loader would look at the app's expectation,
then silently re-interpret the bits in the glTF texture in order to
match this expectation. This seems very wrong.

Instead, if the expectated format does not match the format in the KTX
file, we now print a warning.

Fixes #2422, which will also be obsoleted by our upcoming KTX2 support.
2022-04-12 11:52:36 -07:00
LaiJF d6df4cd03a Fix typo. 2022-04-12 10:57:46 -07:00
Philip Rideout df03fdf3d7 mipgen: fixups / clarification regarding sRGB.
The `g_linearized` variable was being used for two purposes: to denote
the linearity of the source format AND the linearity of the destination
format. This was confusing and is now split is `sourceIsLinear` and
`destIsLinear`.

This change has no effect on the the look of the suzanne demo.
2022-04-11 14:28:34 -07:00
Mathias Agopian 6c59945395 fix typo preventing desktop GL builds to work 2022-04-11 09:51:38 -07:00
Philip Rideout d16cc50561 Shrink BasisU transcoder.
We do not support these formats and they add bloat to the basis tables.
In a release x86 build, this reduces the transcoder size from 774 KiB to
475 KiB.
2022-04-08 15:03:30 -07:00
LaiJF e667484a94 Fix typo. (#5413) 2022-04-08 14:23:46 -07:00
LaiJF 71e5e6c6c0 Fix typo. (#5407) 2022-04-08 14:22:29 -07:00
LaiJF c1df902593 Fix typo. (#5414) 2022-04-08 14:14:47 -07:00
Mathias Agopian 3c3320a2ba we need to be able to query the version before creating OpenGLDriver. 2022-04-07 20:30:11 -07:00
Mathias Agopian 35753bc6c2 CommandStream shouldn't be copyable.
This actually avoids a copy of Dispatcher (which is pretty large)
when constructing Engine.
2022-04-07 14:07:20 -07:00
Mathias Agopian 5f7967d09c Improve HandleAllocator
Allocation and destruction of handles generates a fair amount of code
because they are synchronized and the spinlock is inlined.

So we fix this by generating the 3 (de)allocation methods we really
need, we only need 3 because we're using 3 pools. These are now 
out-of-line, which reduces size and reduces pressure on the i-cache.
Performance is not affected much because in the end it's just a
static branch (and in most case the return is elided).
2022-04-07 14:07:20 -07:00
Mathias Agopian 404b6e8af3 Improve CommandStream Dispatcher
The main change here is that instead of allocating a Dispatcher on the
heap and storing a pointer to it in the CommandStream, we now have
a Dispatcher directly inside the CommandStream.

This avoids a heap allocation and a dereference when executing a command.
2022-04-07 14:07:20 -07:00
Mathias Agopian 898c20e584 OpenGLContext cleanups
the main change here is to make OpenGLContext friendly with ES2
2022-04-07 14:07:20 -07:00
Mathias Agopian f278b76b04 gl backend version management cleanup 2022-04-07 14:07:20 -07:00
Ben Doherty 6353f17635 Releases: specify Python dependencies in requirements.txt file (#5402) 2022-04-07 11:23:03 -07:00
daemyung jang 9cae34babf Add Java binding to get skins in FilamentAsset 2022-04-07 08:53:27 -07:00
Philip Rideout c37cc61b30 Update WebGL demos again. 2022-04-06 11:03:18 -07:00
Philip Rideout 9aced8e9b8 WebGL: fix intermittent 'detached ArrayBuffer' errors.
Partial fix for #5404.
2022-04-06 10:58:30 -07:00
Philip Rideout dde060bf4d Repair iOS build. 2022-04-06 10:56:37 -07:00
Philip Rideout b60518caa5 Add libs/ktxreader, rename some things to prep for KTX2.
Changes:

- Remove the strange header-only variant of libs/image
- Rename KtxBundle => Ktx1Bundle
- Move image/KtxUtility => ktxreader/Ktx1Reader
- Add unit test for Ktx1Reader and test stub for KTX2.

Notes:

- Ktx1Bundle does not depend on Filament and is used by cmgen
  and mipgen to generate KTX files.

- Ktx1Reader has a dependency on Filament and should therefore live in
  a separate library, which it now does.
2022-04-06 10:56:37 -07:00
Philip Rideout 69000ef1f2 Fix online demo.
The `demo_*` web samples were using unpkg to refer to the Filament build
rather than using the local copy, which was inconsistent with the other
web samples.

We now use the local copy of Filament for everything except the
drag-and-drop viewer, which always uses the latest version of Filament.
2022-04-06 09:14:25 -07:00
Philip Rideout 39d6106ef2 Add BasisU to third_party. 2022-04-06 09:02:18 -07:00
Ben Doherty 96a1cbe69f Attempt to fix GitHub release asset upload (#5398) 2022-04-05 13:01:20 -07:00
Benjamin Doherty 09fe495384 Release Filament 1.21.0 2022-04-04 13:00:48 -07:00
Pavel Korolev 8457d6092d Use index offset provided by ImGui when rendering UI 2022-04-04 10:49:43 -07:00
Mathias Agopian 72c16e07ed remove Viewport::scale()
because a float->integer conversion is needed, it's better to let the
caller decide what they want.
2022-04-02 20:37:00 -07:00
Mathias Agopian 12b96cba04 minor cleanup: rename internal class attributes 2022-04-02 20:37:00 -07:00
Mathias Agopian e4d943e942 update release nodes and bump material version 2022-04-02 20:36:40 -07:00
Ben Doherty 7fa66325f3 Fix Metal validation error when reading from default SwapChain (#5392) 2022-04-01 16:37:46 -07:00
Mathias Agopian e188a7875e enable both screen-space refraction and reflection
Both "SSR" can now be used on the same material. This is made possible
by using a 2D array to store both buffers.
2022-04-01 16:22:10 -07:00
Mathias Agopian ac9822b8c8 Fix a framegraph dependency bug when writing to subresources
The dependency graph was set incorrectly when writing to a subresource
of a subresource.
2022-04-01 16:22:10 -07:00
Mathias Agopian edb5fddd03 one more step towards reflection+refraction support
With this change we are now generating refraction and reflections
buffer into their own layer of a 2D array -- so they can coexist.

This change doesn't actually enable both at the same time yet.

There are downsides to this approach:
- a 2d array of 2 layers is created even if only one of reflection or
  refraction is active. This could be fixed at the cost of more
  complexity.
- if reflections are active then refraction must use a RGBA16F texture
  instead of RGB_11_11_10, because they share the texture
2022-04-01 14:37:40 -07:00
Mathias Agopian 35f4a97e32 new framegraph API do add a pass without an execute stage 2022-04-01 14:37:40 -07:00
Mathias Agopian 487b10fdda repair and optimize matdbg
we add a checkProgramEdits() method that must be called periodically
on all materials. This is currently done at the beginning of a frame.
2022-03-31 16:52:26 -07:00
Mathias Agopian 271cda88aa Move vulkan backend implementation into the filament::backend namespace 2022-03-31 11:53:54 -07:00
Mathias Agopian 25b73ddcfa Move opengl backend implementation into the filament::backend namespace 2022-03-31 11:53:54 -07:00
Mathias Agopian 35b8146a87 move metal backend out of the metal namespace
this is to be consistent with other backends, which are all in
filament::backend.

had to rename metal::PipelineState to MetalPipelineState.
2022-03-31 11:53:54 -07:00
Mathias Agopian 091e5a33ac move Noop backend into filament::backend namespace 2022-03-31 11:53:54 -07:00
Ben Doherty ffe4b7390d Correctly prepare color grading as subpass programs (#5384) 2022-03-30 16:25:27 -07:00
Mathias Agopian 604d3e34a4 avoid an extra copy during the screen-space reflection pass
unlike for refraction, the reflection buffer is distinct from "the"
color buffer, this allows an optimization (compared to ssr) when we
generate the mipmap chain -- we can allocate the mipmaped texture
and render the SSR pass directly into its level 0. This achieved
use the framegraph's forward resource feature.
2022-03-30 15:32:52 -07:00
Mathias Agopian e116dd4aec Improve framegraph forward resource API
This add a couple methods to allow the creation and forwarding in a
single call.
2022-03-30 15:32:52 -07:00
Mathias Agopian d53614fb0a fix a framegraph crash when forwarding a subresource
the crash would happen when forwarding a subresource of a subresource,
because in this case the parent's handle would be reset to the null
handle.
2022-03-30 15:32:30 -07:00
Mathias Agopian c91e5df117 Add comment about how we calculate the viewport when upscaling 2022-03-30 08:58:50 -07:00
Philip Rideout 96574816b3 Fix 12x overallocation of memory in MorphTargetBuffer.
I noticed this while helping someone at Google understand our new API.
2022-03-30 08:24:40 -07:00
Mathias Agopian b43a609ebc rename framegraph fg2/ folder to fg/ 2022-03-29 14:38:36 -07:00
Benjamin Doherty 2c490ec799 Release Filament 1.20.5 2022-03-28 18:44:56 -07:00
Mathias Agopian fbb08d338a repair the flare pass on WebGL 2022-03-28 17:01:07 -07:00
Mathias Agopian 8e1718458a remove all references to the "Blackboard" from PostPorcessManager
This makes the code simpler to follow.
2022-03-28 16:23:52 -07:00
Philip Rideout 6bcd709320 gltfio: add support for KHR_materials_emissive_strength 2022-03-28 12:57:08 -07:00
Mathias Agopian 1a6e3ec88e batch all program linking at begin renderpass time
With this change, shaders are compiled at program creation, programs
are linked at the start of the next render pass and queries are
deferred until first use.

This should improve overall performance on some drivers.
2022-03-26 13:36:35 -07:00
Mathias Agopian f5f50eca06 programs must now be created outside of renderpasses
from now on, the backends can assume that programs are created outside
of begin/endRenderpass.
2022-03-26 13:35:48 -07:00
Mathias Agopian 886fb7fb94 fix build 2022-03-26 13:35:18 -07:00
Philip Rideout a82b3bedb2 gltfio: material variants can now be applied to FilamentInstance. 2022-03-25 16:47:59 -07:00
Mathias Agopian d879bbc80a Simplify OpenGLProgram sampler bindings
This reduces the size of OpenGLProgram from 64 to 32 bytes and
improves the code that sets new samplers.

The main simplification is that we're not trying to "pack" the 
texture units used in the program. For e.g. we could be using
units 0,3,4, where before it would be 0,1,2.
This allows us to do less tracking.

Another optimization is that we're discarding entirely a SamplerGroup 
if the program doesn't use any of its samplers. This helps remove
a test in updateSampler which in turn remove somem tracking data.
2022-03-25 15:35:53 -07:00
Mathias Agopian bf437b7933 defer gl program link + query to first use (draw)
in an upcoming PR we'll move linking back a bit earlier to allow
more batching.
2022-03-25 13:47:31 -07:00
Mathias Agopian 49dff3c439 log shader source code in debug build on error 2022-03-25 09:40:11 -07:00
Mathias Agopian 0d6c017cfb cleanup OpenGLProgram
This is the first step before we defer a lot of the glGet* calls.
2022-03-25 09:40:11 -07:00
Philip Rideout ba042db3f4 gltfio Java: add getMorphTargetNames for consistency with other methods.
Tested by hacking ModelViewer.
2022-03-24 19:23:14 -07:00
Philip Rideout faeba6ad95 gltfio: add support for KHR_materials_variants
Tested the Java API by hacking ModelViewer.
Tested the JavaScript API by adding to filament-viewer-test.
2022-03-24 19:23:14 -07:00
Philip Rideout 163e28ca7a Update public web demos (fixes helmet demo) 2022-03-24 16:10:14 -07:00
Philip Rideout 3dbc168d76 Use newer package for LitElement. 2022-03-24 16:04:43 -07:00
Ben Doherty fe49946852 Metal: support blitting from 2D texture arrays (#5357) 2022-03-24 11:38:51 -07:00
Mathias Agopian 6310ea46e3 fix dummy ssr history texture target type 2022-03-23 20:47:20 -07:00
ef8e3e5224 Fix typo. (#5355)
* Fix typo.

* Update filament/src/RenderPass.cpp

Co-authored-by: Romain Guy <romain.guy@gmail.com>

Co-authored-by: Mathias Agopian <pixelflinger@gmail.com>
Co-authored-by: Romain Guy <romain.guy@gmail.com>
2022-03-23 11:29:07 -07:00
Mathias Agopian 26cc722f74 remove SPVRemaper lib, fold it into glslang directly
This avoids a duplication of doc.cpp, the largest compilation unit
(about 650KiB).
2022-03-23 11:27:30 -07:00
Philip Rideout 043fdf7a51 Remove lite flavor from android-utils.
We noticed that the lite flavor isn't actually smaller, plus we need to
rework our Android library hierarchy anyway, so for now let's remove
this.
2022-03-23 11:18:25 -07:00
Mathias Agopian c01105b49a Fix shadow frustum computation wrt projection matrix
Instead of recomputing the Frustum from its 8 vertices, we compute it
from the projection matrix directly. This ensures this works with any
projection matrix.  Building a Frustum object from 8 vertices required
these vertices to be given in a certain order which wasn't correct if
the projection was flipped for instance.

Removed the API to construct a Frustum from vertices.

fixes b/225975881
2022-03-23 09:41:14 -07:00
Philip Rideout f56f5a300c Temporary workaround for WebGL builds on macOS.
Better fix is to replace etc2comp and astcenc with basis.
2022-03-22 22:21:57 -07:00
Mathias Agopian 8b79f3683e skip work when morphtarget weight is zero
fixes #5344
2022-03-22 22:21:41 -07:00
Benjamin Doherty 319bd123ce Fix, use zero texture array when SSR is of 2022-03-22 22:21:14 -07:00
Benjamin Doherty e23243a65b Fix build breakage on Windows 2022-03-22 20:43:50 -07:00
Mathias Agopian c4261a8c10 hide ostream implementation details into ostream.cpp
Fixes #5343
2022-03-22 16:14:13 -07:00
Mathias Agopian 009b58537e move BuilderBase to libutils and rename to PrivateImplementation 2022-03-22 16:14:13 -07:00
Mathias Agopian e51709a4e8 Size optimizations in UniformInterfaceBlock 2022-03-22 15:28:40 -07:00
Mathias Agopian 78813ed9b7 get rid of ShaderStageFlags.h
move its content to DriverEnums.h, we do this because it is used
in libfilabridge, which has an unspoken rule that it only includes
DriverEnums.h.

filabridge also only has a header dependency, so it can't call any
method, not even operator<<.

Also cleanups and simplifications.
2022-03-22 15:28:40 -07:00
Mathias Agopian 2e649a9f16 size optimizations and cleanups of SamplerInterfaceBlock 2022-03-22 15:28:40 -07:00
Mathias Agopian d36783cd1d cleanup a bit metal codegen for samplers
the main change here is that we actually go through all "binding points"
instead of hardcoding the ones we currently use.
2022-03-22 15:28:40 -07:00
Philip Rideout 101a59138c Update the zbloat tool
The tool now works with Python 3 and handles binaries that have multiple
embedded material archives.
2022-03-21 16:13:49 -07:00
Benjamin Doherty 3809259f47 Release Filament 1.20.4 2022-03-21 14:45:00 -07:00
Mathias Agopian e103b28b41 The backend CANNOT depend on filabridge
This would mean that the backend is not independent of our material
system. Thankfully we didn't have too many dependencies that leaked
there.
2022-03-21 13:55:15 -07:00
Mathias Agopian 8e7d0c0df9 Fix a bug in Invocable that prevented function signatures that returned references from working 2022-03-21 13:55:15 -07:00
Mathias Agopian d8845e5fcc greatly simplify SamplerBinderMap
The main simplification is that we don't need an actual map to retrieve
the global offset of a sampler, it can be easily calculated as:
  global_offset = offset_of_the_block + local_offset
2022-03-21 10:54:00 -07:00
Mathias Agopian b2ed544ee8 More cleanups in PostProcessManager 2022-03-21 10:46:55 -07:00
Mathias Agopian a40ee77326 minor cleanups 2022-03-21 10:46:55 -07:00
Mathias Agopian 85135e60c7 Switch SSR texture to 2D array
At this point there is no benefit from doing this, but we'll need this
in a later PR.
2022-03-21 10:46:55 -07:00
Mathias Agopian bee9f160fa gaussian passes now handle 2d arrays better
Instead of passing the level and layer explicitly to gaussianBlurPass,
we rely on the information already contained in the handle. i.e. we
honor the "subresource" part of the handle (if it has one).
In other words, it's now possible to pass a subresource (e.g. a layer)
to generateGaussianMipmap or gaussianBlurPass and things should work as
expected.
2022-03-21 10:46:55 -07:00
Mathias Agopian 64c67258b0 fix FrameGraph dependency issue
The problem here would happen when forwarding a subresource (i.e. 
replacing an existing resource by a subresource) and the existing
resource had been written to. In this situation, the subresource's 
parent needs to depend on the subresource (i.e. as if it was written to
by it). This would normally happen during write() but in this situation,
the write had already happened.
2022-03-21 10:46:39 -07:00
Mathias Agopian 49e0f484e9 fix a framegraph dependency issue
the dependency graph would be incorrectly severed in the situation where
a subresource was written to and later its parent was read from.
In this situation, the parent node is in fact a new version of the 
original parent node, so we need a "read" dependency of the orginal to
the copy (otherwise the orginal node is not a dependent of anyone
and gets culled).
2022-03-21 10:46:39 -07:00
Mathias Agopian dbc78ff0aa Fix screen-space reflections when post-processing and MSAA are off
when we're rendering directly into the swapchain, we can't have a 
history buffer, so in that case we need an intermediate buffer.
2022-03-21 09:10:51 -07:00
Romain Guy ebca955682 Clear warnings 2022-03-19 12:58:18 -07:00
daemyung jang d8ea26e305 Update MAX_MORPH_TARGETS to 256 2022-03-18 15:42:02 -07:00
Philip Rideout 37aafdd912 WebGL endFrame: restore additional default state. 2022-03-18 14:23:08 -07:00
Mathias Agopian edf78afa8e fix warnings from updating macos toolchain 2022-03-17 15:45:09 -07:00
Mathias Agopian 1df4218deb fix python3 detection in cmake 2022-03-17 15:45:09 -07:00
Ben Doherty 1c5715824f Avoid linking clashes with BlueGL and OpenGL (#5323)
Some clients need to link against both Filament and OpenGL. This can lead to symbol clashes under certain circumstances. As a fix, prefix all of our `bluegl` symbols with `bluegl_`. Previously we made this naming change for Windows, but now we'll do it on all platforms for simplicity.
2022-03-17 11:41:38 -07:00
Philip Rideout 6da46b3b62 Repair A2C for opaque views, add field to FrameUniforms. 2022-03-17 10:01:27 -07:00
Philip Rideout e8d8080928 New behavior for BlendingMode::MASKED.
The existing behavior was surprising for users who draw opaque objects
into a semitransparent views, and this was especially evident with
the labels in `TextureLinearInterpolationTest`.

We now disable blending for MASKED, which is what our existing materials
documentation already says. We also now set the fragment alpha to 1 when
the fragment is not discarded, which prevents the "punch through"
effect. This is consistent with ThreeJS.

Fixes #4576.
2022-03-17 10:01:27 -07:00
Philip Rideout e7934314ad WebGL: reset VAO and texture bindings when frame ends. 2022-03-17 10:00:51 -07:00
daemyung jang c79fcf6d8d Fix a typo (#5324) 2022-03-16 08:42:30 -07:00
Mathias Agopian 3eb2a20c7f fix point light lighting with ortho projection
The froxel parameter for the Z slice were not correct.

Fixes #5318
2022-03-15 21:19:25 -07:00
daemyung jang da99fe63be Make public gltfio's math 2022-03-15 09:11:12 -07:00
daemyung jang d9067af3a3 Retrieve skins from FilamentAsset 2022-03-15 09:10:52 -07:00
LaiJF f10bedf186 Fix typo. (#5319) 2022-03-14 19:30:57 -07:00
Mathias Agopian 19b0ad2605 fix a race in jobsystem (2nd attempt)
We were decrementing activeJobCount after removing the job from the
queue, which could cause other threads in the pool to preempt us before
the decrement, causing them to spin forever trying to get a non-existant
job, until the decrement actually happened.

Now we always decrement first and fix-up the count if we couldn't get
a job from the queues. The race is inverted, and doesn't cause threads
to spin a long time.


fixes b/201100123
2022-03-14 16:40:02 -07:00
Philip Rideout 6e7af103d3 Vulkan: misc SwapChain-related cleanup.
This removes some special handling of the default render target lifetime
that is no longer needed, and renames "surface" to "swapChain" where it
is appropriate to do so.
2022-03-14 16:23:31 -07:00
Philip Rideout 8a91723dcf Vulkan cleanup: remove some state from the VulkanDriver class. 2022-03-14 16:23:31 -07:00
Benjamin Doherty 47e30c337e Release Filament 1.20.3 2022-03-14 14:17:25 -07:00
Philip Rideout fb627d8b66 gltfio: decouple MaterialProvider lifetime from AssetLoader.
This is a gltfio API change (!)

Jave clients now need to call destroy on MaterialProvider.

Previously, the Java AssetLoader took over ownership of a native
material provider upon construction, but this was neither documented
nor consistent with the C++ layer. (This is historical; in the past we
did not expose MaterialProvider to Java.)

One motivation for this (aside from API consistency) is that users may
wish to preserve the material cache from one run to another.

Fixes #5132.
2022-03-14 08:56:33 -07:00
Alexander Biggs 1cb59685c5 Fix precondition for morph weights. (#5308)
Was checking for `MAX - 1` instead of `MAX`.
2022-03-10 16:46:33 -08:00
Mathias Agopian 2b395f1d89 minor ResourceList cleanup 2022-03-10 16:20:36 -08:00
Mathias Agopian e9718fa346 cleanup attributes/varyings generation
We now have a single varyings.glsl containing our varyings for both
the vertex and fragment shader. This file is included with the right
definition of VARYING as `in` or `out`.

inputs.vs is now renamed attributes.vs
2022-03-10 16:20:18 -08:00
Philip Rideout 81fc2c1d23 Always apply bone matrices, even for non-animated models.
This changes the WebGL and desktop glTF viewers so that they always
call `updateBoneMatrices`, even when there are 0 animations. Note
that our Android sample was already doing this correctly.

When combined with #5301, this fixes #5299, although users would need to
use the `recomputeBoundingBoxes` feature in gltfio (`-r` in the desktop
viewer) for this model to be scaled to fill the viewport, since its
embedded bounds are quite large.
2022-03-10 13:41:35 -08:00
Philip Rideout dc60f57a9a gltfio: simplify API, make animator always available.
In the past there was an API gotcha because users had to "get" the
animator before releasing the glTF source data. This could have been
surprising because it was a getter method, not a factory method.

This was due to overeager optimization on my part, I wanted to avoid
animator overhead for non-animated models, when in fact it has very
little overhead.

Moreover, the animator is conceivably useful even when there are no
pre-supplied animations (e.g. for applying skins), so let's just create
it unconditionally.

Motivated by #5299.
2022-03-10 11:36:46 -08:00
Mathias Agopian 5c4f12fa00 create only a single "default render target"
we didn't need one per Renderer, and doing so created complexity in the
backends.

fixes #5291
2022-03-10 11:29:17 -08:00
Romain Guy 00ffd9ca74 Update README.md 2022-03-10 11:02:06 -08:00
daemyung jang 166f859c72 Retrieve morph target count from the primitive (#5297)
Morph weights can be zero even if the primitive has morph targets.
2022-03-10 10:56:50 -08:00
daemyung jangandMathias Agopian 1969186fe1 Compute the rotation between two vectors (#5288)
Co-authored-by: Mathias Agopian <pixelflinger@gmail.com>
2022-03-10 10:42:44 -08:00
Philip Rideout e1e7854d97 BlueVK: remove flaky operator<< for flags, update GitHub paths.
Two changes:

1) Khronos has moved from "master" to "main".

2) BlueVK was attempting to generate reasonable "operator<<" support for
bit flags but this was buggy due to type aliases. Since we weren't using
it anyway, I simply removed this functionality from BlueVK.
2022-03-08 16:58:21 -08:00
Philip Rideout 9d5220e28e Regenerate BlueVK for Vulkan 1.3. 2022-03-08 16:57:56 -08:00
Philip Rideout fc0b41d587 VulkanTexture: remove VkAspect state, derive it on the fly.
This fixes a validation warning, since not all depth textures are
necessarily used as depth attachments.
2022-03-08 14:24:44 -08:00
Benjamin Doherty e4cb861817 Release Filament 1.20.2 2022-03-07 14:09:43 -08:00
Mathias Agopian 640f080ea6 fix TargetBufferInfo uses an union for the face (uint8_t) and layer (uint16_t)
Instead of having 2 fields we're following the vulkan convention of
having only the layer field.

The layer/face convention is still maintained in the public APIs.

fixes #5273
2022-03-04 17:00:37 -08:00
Philip Rideout eed4b3b839 Add comments about validation to Vulkan backend. 2022-03-04 14:10:14 -08:00
Philip Rideout f48dafe87e Update remote page to fix invalid generic tone mapper key. 2022-03-04 09:47:53 -08:00
Philip Rideout daff8fea9f Android Viewer: fix URI bug when dropping some zips.
Dragging a zip file into the Remote Viewer page would fail if it
contained a glTF with `./` prefixes in the `images` section. The best
fix is to use Java's proper URI object rather than trying to parse the
string.
2022-03-04 09:15:37 -08:00
Philip Rideout 51b4a38e20 DriverAPI: add isAutoDepthResolveSupported query. 2022-03-03 14:59:20 -08:00
Philip Rideout 2171e372ce Vulkan: assert if Filament asks to resolve depth in the render pass. 2022-03-03 14:59:20 -08:00
Philip Rideout 1a30709121 Fix Android warnings in Vulkan backend. 2022-03-03 10:37:53 -08:00
Philip Rideout 2ed9b11f50 Bring back initialization of DummyMorphTarget.
This fixes "uninitialized texture" warnings from the Vulkan backend
when viewing Littlest Tokyo in a debug build.
2022-03-02 16:15:57 -08:00
Benjamin Doherty 1797ff5d90 Release Filament 1.20.1 2022-03-02 15:46:41 -08:00
Philip Rideout 8c46e6de9b matdbg: repair invalid JSON and display of active variants.
The JSON response to /api/active became malformed after #4465 because
raw hex strings need to be enclosed by quotes.

This commit changes the variant format in the /api/materials response
to be consistent with one used for /api/active. By using integers
instead of strings, we're avoiding the need to parse integers at run
time.

The JSON error did not appear in the Chrome console because it was being
silenced as a hack to appease "matinfo --web-server". I fix this by
removing the hack and simply emitting a valid response when there's
no live backend.

Also fixed the display of materials, which were always being marked
as active even when they had no active variants.
2022-03-02 15:01:25 -08:00
Philip Rideout 613adfa342 VulkanPipelineCache: fix use-after-free when growing pool.
We held a reference to a cache item after potentially clearing it due to
pool growth. I was able to trigger an error only after enabling ASAN and
loading a large model.  Many thanks to @jeanlemotan for catching this.
2022-03-02 14:59:10 -08:00
Philip Rideout 684b0622eb Vulkan: fix logic that determines when to grow descriptor pool.
When we added per-layout arenas for each of the 3 descriptor types, we
did not account for them when determining how much of the Vk Pool is in
use. Therefore the "growth" (really a re-creation) of the Vk Pool wasn't
always occurring when necessary, causing descriptor set allocation to
fail with large models.
2022-03-02 12:39:33 -08:00
Philip Rideout 426f345f19 Minor updates to how we include vk_mem_alloc.
In the current version of the library, it looks like the DYNAMIC config
macro has been replaced with a STATIC config macro.

Also disabled the "unused-private-field" warning since this is a 3rd
party library and its not our fault.
2022-03-02 12:37:14 -08:00
Ben Doherty f80df6e061 Make VulkanContext compatible with vk_mem_alloc dev 2022-03-02 12:10:45 -08:00
Ben Doherty e2177e8b36 Apply some clang-tidy fixes (#5281) 2022-03-02 11:49:45 -08:00
chubei-oppen 37353cca55 android-utils: Copy bug fixes from upstream (#5279) 2022-03-01 17:32:40 -10:00
chubei-oppen c72817fc25 Bugfix: Mat4 from Quaternion was transposed (#5277) 2022-03-01 10:08:27 -08:00
Mathias Agopian 81c1d3ed1a more code size reduction
The main change here is from ResourceList which ended-up generating
a lot of code due to inlining. This class is only used for tracking
user resources and is not in the performance path.

This saves another ~5K or so of code.
2022-03-01 10:03:31 -08:00
Mathias Agopian 0e1234c57d move the component manager thunks into their own cpp 2022-03-01 10:03:31 -08:00
Mathias Agopian 50fa816a6e fight more unnecessary inlining 2022-03-01 10:03:31 -08:00
Philip Rideout 07f4211dd3 Vulkan: cleanup as per code review. 2022-03-01 08:04:42 -08:00
Philip Rideout 44a433398f Vulkan: shrink DescriptorKey. 2022-03-01 08:04:42 -08:00
Philip Rideout 6821cb60b5 Vulkan: shrink PipelineKey from 608 bytes to 304 bytes. 2022-03-01 08:04:42 -08:00
Philip Rideout b8788bc390 Minor refactoring in VulkanSwapChain. 2022-03-01 08:04:42 -08:00
Philip Rideout 94c59d9d97 libutils: fix inconsistent hash in StaticString
This caused a unit test failure because a StaticString constructed
from "make" had a different hash than one constructed from a literal,
even though the two strings were lexigraphically equivalent.
2022-02-28 15:42:06 -08:00
daemyung jang 5201b5a1ba Decouple the morphing from the render primitive (#5216)
Having MorphTargetBuffer in FRenderPrimitive is a concept of glTF. Filament doesn't have to follow this concept. Actually the responsibility of FRenderPrimitive is to define vertex input stream because FRenderPrimitive maps to HwRenderPrimitive in Filament. If we store MorphTargetBuffer into FRenderPrimitive then it exceeds the responsibility of FRenderPrimitive. Because MorphTargetBuffer doesn't have any information on how to set up vertex input stream. So handling morphing like skinning will be better.
2022-02-28 11:36:52 -08:00
Philip Rideout 215ef460ef Update Vulkan Memory Allocator to v2.3.0 2022-02-28 11:18:34 -08:00
Philip Rideout 90be8ebfa2 Metal: fix bad upload size in blitDepthPlane.
This was caught by ASAN.
2022-02-28 10:33:42 -08:00
Mathias Agopian f62d58bd45 don't inline the command dispatcher ctor
We were basically getting two copies.
2022-02-25 13:19:31 -08:00
Mathias Agopian 9e5da2d75f more size optimizations 2022-02-25 13:19:31 -08:00
Mathias Agopian e12f079ac1 don't prevent unrolling of libmath == operator
We were not unrolling the == loop because the generated code with
unrolling was very branchy; but that's not a good call either because
the loop has the same number of unpredicted branches.
Theoretically the compiler should be able to emit a branchless == but
it doesn't. At least we give it a chance.
2022-02-25 13:19:31 -08:00
Philip Rideout 3c0f18753f GLTFIO_LITE does not need volume texture. 2022-02-25 09:28:17 -08:00
Mathias Agopian a0e4d3df32 fix android build 2022-02-24 22:43:53 -08:00
Mathias Agopian 4f590e3326 uninline some non performance critical setters 2022-02-24 20:59:21 -08:00
Mathias Agopian 6fdfe606e6 move all public trampolines into their own cpp file
This should prevent code duplication due to agressive inlining.
2022-02-24 20:59:21 -08:00
Mathias Agopian 1baab6c3ae move all 'F' classes into src/details 2022-02-24 20:59:21 -08:00
Mathias Agopian 61e67a2766 clenaup 2022-02-24 20:59:21 -08:00
Philip Rideout 8277015785 Vulkan: Fix regression with IridescentDishWithOlives.
When we introduced texture-based morphing, our custom depth resolver
needed to be updated to set up samplers correctly. This fixes a
validation error about shader stage access.
2022-02-24 15:03:23 -08:00
Philip Rideout 97952e0ddc gltfio ubershader: provide dummy texture for volume thickness.
Fixes logcat spam seen with IridescentDishWithOlives.
2022-02-24 15:02:30 -08:00
Benjamin Doherty b80d73f3cf Release Filament 1.20.0 2022-02-24 13:55:33 -08:00
Philip Rideout a1bf6a427d Enhancement for FILAMENT_VULKAN_VERBOSE. 2022-02-24 11:18:48 -08:00
Philip Rideout 67144bec73 Fix build when FILAMENT_VULKAN_VERBOSE is enabled. 2022-02-24 11:11:15 -08:00
Ben Doherty f801763e6b Add SSR variant filter to matc (#5256) 2022-02-24 10:35:30 -08:00
Philip Rideout 542dd331d7 Vulkan: Add asserts that check render target size. 2022-02-24 09:26:32 -08:00
chubei-oppen 4ac3454dc6 Bugfix: The first image passed to Stream::SetAcquiredImage is ignored and leaked 2022-02-24 09:25:14 -08:00
chubei-oppen 23b578ef89 Bugfix: lookAt z axis negated 2022-02-24 09:24:57 -08:00
daemyung jang b6c26ab4e4 Guarantee Texture's minimum width and height must be 1 2022-02-24 09:23:07 -08:00
Philip Rideout 4fbcfc3168 Engine: fill dummy textures with zeroes or ones. 2022-02-24 09:04:17 -08:00
Philip Rideout 9d0aab4d21 Vulkan: be graceful when apps use uninitialized textures.
This makes it so that we emit a nice error message instead of triggering
a hairy validation error due to UNDEFINED image layout.
2022-02-24 09:02:08 -08:00
Philip Rideout 6420bc6dd8 Vulkan: fix backend tests (especially ReadPixels Y flip). 2022-02-23 10:16:53 -08:00
Mathias Agopian 9fa41d06d6 FrameGraphHandle can be trivial for function calls 2022-02-23 09:52:17 -08:00
Mathias Agopian 805227d6fc improve PostProcessMaterial 2022-02-23 09:52:17 -08:00
Mathias Agopian 67d4632868 user c-array instead of vector<> in hot loop 2022-02-23 09:52:17 -08:00
Mathias Agopian 7efe967add don't inline ctor/dtor that have vector<> 2022-02-23 09:52:17 -08:00
Mathias Agopian a8cdfc6b23 Make sure Handle<> is trivial for function calls
This allows small-struct calling convention with most ABIs.
2022-02-23 09:52:17 -08:00
Mathias Agopian 7964ebf3c5 Some method really don’t need to be inlined 2022-02-23 09:52:17 -08:00
Ben Doherty 49b8e5e5d2 Adding missing algorithm include (#5237) 2022-02-22 18:06:53 -08:00
Philip Rideout 54e6b6b24a Vulkan: fix issue with MSAA sidecar dimensions.
Every sidecar texture should have the same dimensions as its parent
texture.

Prior to this change, the sidecar texture would have the dimensions of
the RenderTarget wrapper rather than the parent texture. This was wrong
because the RenderTarget might be slightly smaller than the texture.
This caused an issue when the same texture was attached to two render
targets with different sizes, because there's only 1 cached sidecar per
texture.
2022-02-22 17:35:08 -08:00
Philip Rideout 0fe6cfb224 Vulkan: fix lifetime issue with sidecar depth.
We were passing the wrong texture object to VulkanDisposer::acquire().
MSAA depth sidecar textures are not managed by VulkanDisposer, but their
parent textures are.

Fixes #5217.
2022-02-22 17:34:31 -08:00
Philip Rideout 0ee540df9c Vulkan: fix hack, allow SSAO to read from all mips.
When we overhauled image layout transitions, we moved as many
transitions as possible into the render pass. However the transition
that we perform for "depth read only" layout needs to be applied to
multiple miplevels, so we cannot use the render pass for that.
2022-02-22 17:34:18 -08:00
Philip Rideout 249f0a80d8 gltfio: be graceful when model has > 4 weights per vert.
We now handle "too many bone weights" in the same way that we handle
"too many UV sets".  i.e. emit an error message and do not panic.

This change allows us to render the model in #5234 quite reasonably.

Fixes #5234.
2022-02-22 17:34:02 -08:00
Philip Rideout b3368a3fb2 Vulkan: make validation messages slightly easier to read. 2022-02-22 09:10:05 -08:00
Philip Rideout 327576274f Fix web apps that have multiple Filament viewers.
This fixes the emscripten binding errors that we've been seeing
with the <filament-viewer> test page, which prevented us from
including web in the last few Filament releases.

The binding errors were caused by double-initializing the emscripten
module.

I fixed this by allowing clients (e.g. FilamentViewer) to call
Filament.init() more than once. We now accumulate a list of "on ready"
callbacks that get triggered after the emscripten module becomes ready.

As far as I can tell, multiple canvases were actually always broken, and
the viewer test page worked in the past only because we got lucky.
2022-02-22 08:42:36 -08:00
Mathias Agopian 0e7004a7f8 Automatically set read-only depth in the framefraph 2022-02-18 14:42:35 -08:00
Philip Rideout ca8549549c Fix build break. 2022-02-18 14:41:59 -08:00
Philip Rideout fa6d9a4b01 Upgrade emsripten to 3.1.5 2022-02-18 14:36:20 -08:00
Mathias Agopian 3693e4909b Workaround feedback loops limitation in GLES 2022-02-18 13:51:01 -08:00
Mathias Agopian 697a8370cb There was still a case where skinning wasn’t correctly default initialized
Fixes: #5185
2022-02-18 13:49:12 -08:00
Philip Rideout 155a362d60 Fix warning. 2022-02-18 13:37:28 -08:00
Philip Rideout fed95d70b0 Vulkan: ensure that desired present mode is actually supported. 2022-02-18 11:20:52 -08:00
Philip Rideout cd126138e0 Clean up readOnlyDepthStencil as per code review. 2022-02-18 10:00:06 -08:00
Philip Rideout 7e7398aa92 Assert valid usage of readOnlyDepthStencil in debug builds. 2022-02-18 10:00:06 -08:00
Philip Rideout ede7c579f9 Add new backend hint to RenderPassParams.
Previously, the Vulkan backend made an educated guess about the depth
write state during the start of the render pass. The logic for this
did not make any sense, so now we're replacing it with an explicit
hint that PostProcessManager sets up. In a sense this gives backends
a sneak peek into the raster state.
2022-02-18 10:00:06 -08:00
Philip Rideout 67aa6f1913 Update old comments about max color attachment count. 2022-02-17 12:55:31 -08:00
Philip Rideout 80eba1de10 VulkanRenderTarget: remove duplicated state tracking.
Now that VulkanRenderTarget is always backed by textures, it no longer
needs to track state that is already tracked by VulkanTexture.
2022-02-17 08:31:02 -08:00
Philip Rideout 5e05a23e94 Vulkan: Remove duplicated layout tracking. 2022-02-16 16:21:07 -08:00
Philip Rideout 8c8061a637 Vulkan: simplify management of "default" render target. 2022-02-16 16:21:07 -08:00
Philip Rideout 9ef3c59698 Vulkan: clean up the SSAO image layout workaround. 2022-02-16 16:21:07 -08:00
Mathias Agopian 5f7c6c2fbf update material version
This this needed by recent SSR changes.
2022-02-16 11:20:28 -08:00
Mathias Agopian 991360da97 Missing public modifier in Texture.java
Fixes #5210
2022-02-16 10:24:20 -08:00
Mathias Agopian 50d9fb2b5b Fix typo in documentation
Fixes #5150
2022-02-16 10:23:59 -08:00
daemyung jang 001a3e3dc8 Set the morph target buffer by builder (#5179) 2022-02-16 09:20:38 -08:00
Romain Guy b6eca61786 Update Gradle (#5208)
* Update Gradle

* Add comment
2022-02-15 17:01:17 -08:00
Philip Rideout cc75eb3aa2 Vulkan: add comments explaining layout strategy. 2022-02-15 15:47:17 -08:00
Philip Rideout f5fda88cf6 Vulkan: clean up ReadPixels and Blit paths.
VulkanSwapChain is now always backed by VulkanTexture, so these
code paths can be simplified.
2022-02-15 15:47:17 -08:00
Philip Rideout e99f13b14d Fix some RangeMap behavior and improve its unit test.
The existing unit test had an incorrect expectation in what happens
after splicing an existing range. Fixing the unit test revealed an
actual bug in the RangeMap implementation. It should never modify the
lower bound of an existing interval, because that invalidates the
iterator. It should also never retain a pointer or reference to a range
when the range is potentially removed by subsequent codelines.
2022-02-15 15:46:34 -08:00
Romain Guy 08e809bf75 Update Android tooling (#5204)
* Update Android tooling

* Don't update AGP
2022-02-15 13:22:30 -08:00
Mathias Agopian 1d6aeb5de1 Add basic support for instanced renderables
We can now specify an "instance count" per renderable during creation. 
This instance count applies to all render primitives in the 
Renderable.

This will simply draw the renderable "instance count" times. A new
method available to vertex shaders, getInstanceIndex(), allows the
material to discriminate the instances and adjust the position/transform
accordingly.

Typically this is used for particle systems.
2022-02-15 13:11:23 -08:00
Mathias Agopian d13ccd1c26 instancing support for the backends
We just add an instance count to the backend draw command.
2022-02-15 13:11:23 -08:00
Ben Doherty 54482e6451 Attempt to fix Windows CI builds (#5205) 2022-02-15 11:11:28 -08:00
Romain Guy 9491b36a25 It's ok compiler, it's ok 2022-02-15 08:17:10 -08:00
Mathias Agopian d387e14d4c cleanup TAA
The new SSR code allows to clean-up TAA code a bit.
TAA should now be more standalone/abstracted.
2022-02-14 16:43:24 -08:00
daemyung jang 5c41b332ad Add Java binding to get morph target names 2022-02-14 16:40:32 -08:00
Benjamin Doherty fd69c7ed75 Release Filament 1.19.0 2022-02-14 13:46:06 -08:00
Philip Rideout 3ff8d6dc22 Incorporate code review feedback. 2022-02-14 13:00:12 -08:00
Philip Rideout af6fd21e11 Crucial refactoring of VulkanFboCache and VulkanSwapChain.
Two big changes to simplify and fix layout transitions:

(1) The RenderPassKey struct has been reduced from 88 bytes to 56 bytes
by using custom enum types and bitmasks. It also now has separate fields
for "final" and "initial" image layouts.

(2) VulkanSwapChain now leverages VulkanTexture, which enables it to
share tracking functionality, avoid duplicated state, and have less code
overall.

In a future PR we will clean up the ReadPixels and Blit paths, and also
remove some hacks that appease Vulkan when SSAO is enabled.
2022-02-14 13:00:12 -08:00
Mathias Agopian 5bd5c50c8d Remove unit test that is not very useful. 2022-02-14 12:03:07 -08:00
Elie Michel 2c8d296044 Make sure one use the right combination of version
To avoid `Material version mismatch`
2022-02-14 10:55:55 -08:00
Mathias Agopian df6a100fcb Improve how we compute the lod from the roughness
The main change here is that for screen-space reflections, the lod
calculation takes the camera distance into account.

We also now correctly take into account that we blur each lod
successively which increases the standard deviation by 10%. This applies
to both refraction and reflection.
2022-02-13 22:53:47 -08:00
Mathias Agopian 3f6188edff Enable rough reflections
This works by first generating a reflection buffer which gets blurred,
then the color pass samples from this buffer according to the roughness
of the surface being rendered.

A lot of the changes here involve utilizing "reserved" variants for
the new "SSR" pass and all the fallout from that.
2022-02-13 22:53:47 -08:00
Mathias Agopian cc0486b3cc Rework material Variant filters
Variants are no longer just a bit mask, but rather a combination of
some bits, depending on the variant. Because of that the variant filer
must be updated.

Basically we now make a distinction between the "variants" as a public
material API and the actual `Variant` data type.

This change does the impedance match between the two.
2022-02-13 22:53:47 -08:00
Mathias Agopian 8314bafc0e reformat Variant.h
indentation was wrong
2022-02-13 22:53:47 -08:00
daemyung jang 764c695e4e Fix typos 2022-02-12 19:30:19 -08:00
Philip Rideout 808ca42992 Vulkan: fix segfault during shutdown. 2022-02-11 16:45:23 -08:00
Philip Rideout 4a8428318b Refactor VulkanSwapChain to prep for image layout cleanup. 2022-02-11 14:50:51 -08:00
Philip Rideout c93059783b VulkanDriver: fix VkImageView mismatch in render pass logic. 2022-02-11 14:50:51 -08:00
Mathias Agopian d21f092645 make sure skinning bones are correctly initialized
Fixes: #5185
2022-02-10 20:34:53 -08:00
daemyung jang 9844803b26 Add function overloading for setMorphTargetBufferAt (#5169) 2022-02-10 15:55:41 -08:00
Philip Rideout 2e0ace5026 WebGL: another fix for BufferDescriptor bindings.
The previous code would convert each element of the source data
into 8 bit-per-element, but we wnat to preserve the original format
that the user provides.

The new solution is to use `slice()` which is a robust way to clone
all the data in a typed array.

This fixes the new regression with Triangle that Ben caught.
2022-02-09 15:41:15 -08:00
Philip Rideout b8725ffa22 WebGL: remove buffer sharing optimization.
If emscripten grows the heap inside one of our BufferDescriptor binding
functions, then the old heap becomes "detached" and an error can
occur.

This fixes the issue seen with the Parquet demo that Ben caught.
2022-02-09 12:29:54 -08:00
Mathias Agopian d2da478923 Added Scene::forEach to iterate through a scene's entities
Fixes #3010
2022-02-08 20:23:57 -08:00
Mathias Agopian 0b3e557b65 New Invokable function wrapper 2022-02-08 20:23:57 -08:00
daemyung jang 0d2faa4573 Revert adding APIs 2022-02-08 10:31:17 -08:00
daemyung jang 1924810c17 Deprecate MorphHelper
These changes bring the loading performance optimization by removing
flush and wait.
2022-02-08 10:31:17 -08:00
daemyung jang 6ab45a4cf0 Fix an annotation for the morph target count
Filament now supports the number of morph target up to 256.
2022-02-08 10:23:49 -08:00
Benjamin Doherty 5e2c94c31a Release Filament 1.18.0 2022-02-08 09:18:10 -08:00
Philip Rideout c1a99921b0 Vulkan: fix leak when apps do not draw anything. 2022-02-07 14:26:27 -08:00
Mathias Agopian 4a0dbbce12 fix typo in RenderTarget::build attachment size validation
the validation could fail if attachments used different LODs but the
sizes still matched.
2022-02-07 13:40:34 -08:00
Benjamin Doherty 7398183d6f Bump material version 2022-02-07 11:28:45 -08:00
Benjamin Doherty edf405c8fd Fix RELEASE_NOTES 2022-02-07 11:24:50 -08:00
Ben Doherty 4cc8f88a21 Add a MAX_LEGACY_MORPH_TARGETS definition (#5163) 2022-02-07 11:23:49 -08:00
Mathias Agopian 5dba7fdae0 move generateGaussianMipmap to PostProcessManager
also, allow it to specify the output format.
2022-02-04 16:24:27 -08:00
Ben Doherty e2b8573bd7 Initialize useLegacyMorphing to fix MSAN warning (#5164) 2022-02-04 14:43:18 -08:00
Mathias Agopian 6eeb4c9d3a refactor refraction code
filament/src/Renderer.cpp
- make code mode readable, hopefully
- SSR mipmap generation is now more or less standalone
- when possible, resolve color buffer directly into
  mimpmapped texture's base level.
2022-02-04 11:18:16 -08:00
daemyung jang 996981b102 Change CONFIG_MAX_MORPH_TARGET_COUNT's type correctly
CONFIG_MAX_MORPH_TARGET_COUNT should be positive value so size_t is
proper than int.
2022-02-04 11:17:58 -08:00
daemyung jang 4f4330c95e Update RELEASE_NOTES.md 2022-02-04 11:17:58 -08:00
daemyung jang e48f54a863 Fix validation errors on Metal 2022-02-04 11:17:23 -08:00
Philip Rideout 2aa8ea4687 Rewrite VulkanPipelineCache (without changing its API).
All three types of caches (descriptor sets, pipelines, and pipeline
layouts) are now managed in exactly the same way. They all use an LRU
eviction scheme that is based on a count of command buffer flush
events.

Vulkan objects can only be destroyed if there are no in-flight command
buffers that reference them, so an easy way to know when it is safe to
evict a given entry is to wait for "N" flushes after its last use, where
"N" is the number of command buffers in the command buffer ring.

Another big simplification is that there are no more dirty flags,
instead we store two sets of state vectors for each type of cache: the
"currently bound" state, and the "current requirements" state.
2022-02-03 17:36:57 -08:00
Mathias Agopian cde055e5bf Minor cleanups
- Rename projectToPixelMatrix to uvFromViewMatrix, this match our 
existing style better.

- slightly more efficient direction transform

- limit roughness to 0.1 instead of 0.01, because in a lot of cases, 
the roughness increases with the LOD, for instance if it comes from
a texture (to combat aliasing).
2022-02-03 14:54:03 -08:00
Mathias Agopian 19729db982 turns out GLES3.x forbids depth texture filtering
warn about this condition on debug builds
2022-02-03 14:28:28 -08:00
daemyung jang 2029c9584e Get the morph target count from glTF
glTF spec says that all primitives MUST have the same number of morph
targets in the same order so these changes are more correct.
2022-02-03 13:26:09 -08:00
Ben Doherty d9cbe60ca6 Fix NaN values encountered with SSR and Metal (#5156) 2022-02-03 13:24:43 -08:00
Romain Guy 04337fdb68 Update Kotlin math API to latest (#5152)
Changes incorporated from github.com/romainguy/kotlin-math
2022-02-03 12:17:21 -08:00
daemyung jang a43b17716f Pass the current variant to GLSLPostProcessor
The current Variant is need to calculate BindingIndexMap correctly.
But we can't use the current Variant when calculate BindingIndexMap
because SamplerBindingMap uses only the dummy Variant. Both are
should be same.
2022-02-02 11:59:04 -08:00
daemyung jang 63032ed0a6 Add the morphing sampler group always
The morphing sampler group can be added if skinning or morphing is
enabled. However SamplerBindingMap can't know skinning or morphing
is enabled because only dummy Variant is used. It causes generating
the different sampler bindings between SamplerBindingMap and
program's sampler groups.

Fixes #5139
2022-02-02 11:59:04 -08:00
Ben Doherty b6cd6668a6 Fix sampler overflow check in SamplerBindingMap (#5143) 2022-02-02 11:04:08 -08:00
Romain Guy dee41e6120 Fix notebook 2022-02-02 10:04:48 -08:00
Mathias Agopian 7b03cb9b76 A few screen space reflections improvements
- Make sure to disabled SSR when it's... disabled.

- Fade the reflection when the ray direction is towards de camera,
  where it will likely hit a back face

- Simplify the fading code, for near identical results.
2022-02-02 09:36:20 -08:00
Philip Rideout 8aa83d4886 VulkanPipelineCache: fix spurious SEGV.
Fixes #5142 by replacing unsafe pointers with map keys.

One of the differences between robin_map and unordered_map is the
following:

    pointers to keys or values in the map are invalidated in the same
    way as iterators to these keys-values

Therefore it is unsafe to track the pointer to a value that is stored
in a robin_map.
2022-02-01 16:35:34 -08:00
Philip Rideout c17b3756ea VulkanPipelineCache: code cleanup and minor fixes.
This is mostly just code cleanup. One actual bug was the fact that the
dummy sampler was re-created every time a new pipeline layout was
created.

It also felt strange to use `auto&` to refer to a C-style array. I
changed this into a `std::array` which is more consistent with other
fixed size arrays in this class.
2022-02-01 16:35:34 -08:00
Mathias Agopian 73e339b05d be more consistant with defines names in shaders
all defines coming from material parameters are named `MATERIAL_HAS_...` 
and all defines coming from the variant are named `VARIANT_HAS_...`
2022-01-31 22:53:48 -08:00
Ben Doherty 42172c7395 Add iterator include to Range.h (#5141) 2022-01-31 12:54:27 -08:00
Philip Rideout fbc0b8dab5 gltf_viewer: fix bad ReadPixels size in headless mode
This fixes the gltf_viewer automated testing mode, invoked via
`--batch=default --headless`.

ReadPixels was being issued with an out-of-bounds size on high DPI
platforms, which caused weird backend errors.

Since we create an invisible SDL window while in headless mode, the
presence of the SDL window does *not* indicate headless vs non-headless.

Partial fix for #5111
2022-01-31 11:34:13 -08:00
Mathias Agopian 91b45d2890 fix an out-of-bound access when setting morphing buffer
Because the morphing buffer is actually a texture, it's possible that
the last line is not a full width when updating the buffer.
Because texture are updated via a rectangle, it was possible to read
past the malloc'ed buffer during the update.

Moreover, because the count can be specified, we can't just blindly send
more "dummy" data. 

Finally, added an offset to match the skinning API, and in that case, 
the first line can also be incomplete.


We fix this by issuing up to 3 texture update calls if needed.


The java/js API update will come later.
2022-01-30 16:53:11 -08:00
daemyung jang 9df13c1cd2 Cleanup code 2022-01-28 21:41:19 -08:00
daemyung jangandMathias Agopian 5a3853a442 Optimize memory of MorphTargetBuffer (#5046)
* Optimize memory of MorphTargetBuffer

Co-authored-by: Mathias Agopian <mathias@google.com>
2022-01-27 21:19:13 -08:00
Mathias Agopian 70e14a1757 try to workaround optimizer/compiler bugs
Fixes #5088
2022-01-27 19:24:11 -08:00
Ben Doherty 4c4a93d9b5 Support legacy morphing (#5129)
Support legacy morphing (morphing with targets supplied via VertexAttributes) for older clients. This gives clients more time to transition over to the new MorphTargetBuffer API.
2022-01-27 16:16:53 -08:00
Mathias Agopian 001dcefd8a simplify how we select a material Variant
Instead of building the Variant based on flags in RenderPass, we just
pass the Variant itself to RenderPass. The caller has more knowledge
of what it wants to do.
2022-01-27 15:48:24 -08:00
Mathias Agopian d114d547be update material version to 18 2022-01-26 14:49:09 -08:00
Philip Rideout 6403e0ce44 gltfio morphing: generate normals when they are missing.
This allows the `Horse.glb` model to work with Vulkan without any
validation errors. As a reminder, the glTF spec says:

```
When normals are not specified, client implementations MUST calculate
flat normals
```

Fixes #5115.
2022-01-26 13:48:05 -08:00
41cf507746 Bind samplers to specified shader stages (#5036)
Co-authored-by: Ben Doherty <bendoherty@google.com>
Co-authored-by: Mathias Agopian <mathias@google.com>
2022-01-26 12:22:07 -08:00
HanYunChenLuo c49fcf9018 WebGL: Support compile filament.wasm on Linux platform. (#5120) 2022-01-26 10:28:03 -08:00
daemyung jangandMathias Agopian 354c39be6b Get the morph target count from the renderable (#5077)
* Get the morph target count from the renderable
* Set the morph target count by Builder
* Update morph target weights partially
* Remove noexcept at functions could throw exceptions
* Update Java bindings at RenderableManager
* Add missing comments
* Update morph target weights from offset

Co-authored-by: Mathias Agopian <mathias@google.com>
2022-01-26 10:27:25 -08:00
wangjinhan 26bbe8ade1 fix build android aar on Linux because of case sensitive 2022-01-25 22:39:40 -08:00
daemyung jang 1952f0a1f7 Change morphing APIs to support LOD (#5080)
* Change morphing APIs to support LOD
* Add Java and Web bindings for morphing
* Omit and fix JS bindings
* Fix styles in MorphTargetBuffer.java
2022-01-25 21:57:11 -08:00
daemyung jang 61fdc0d375 Fix styles in SkinningBuffer.java (#5117) 2022-01-25 21:46:55 -08:00
Mathias Agopian 4060b558c7 Minor optimizations and documentation cleanup
- Document that both positions and tangents must be provided.
- Don't memset buffer before filling it
- Don't read 4 identical weights in shader
2022-01-25 17:16:43 -08:00
Philip Rideout a783df39ba Vulkan now supports offsets when uploading texture data.
This allows `MorphStressTest` to work on Vulkan.

However, `Horse` is still broken because it provides positions but not
tangents.  Separate fix for that is coming.

Partial fix for #5109.
2022-01-25 17:06:33 -08:00
Philip Rideout a9ccaf2ffb Vulkan: clean up image layout management.
This fixes validation errors and makes a first pass at simplification.
VulkanTexture now tracks image layout using RangeMap, which paves the
way for further simplification.
2022-01-25 15:45:58 -08:00
Mathias Agopian f40b08d826 Simplify and optimize morphing
There is no need to go through all primitive and call updateSamplerGroup,
because the SamplerGroup never changes -- it just hold the texture that
holds the data.
2022-01-25 14:08:15 -08:00
Mathias Agopian 9fd0397d45 A morphing buffer must be bound when skinning is active
This is because we're using the same program variant for skinning
and morphing, in the skinning-only case, the buffer won't be accessed
in the shader, but it must be present.

fixes #5085
2022-01-25 13:11:02 -08:00
Philip Rideout 69fb7170a7 Fix typo in BlueVK script that caused segfault.
Fixes #5026.
2022-01-25 10:23:07 -08:00
Mathias Agopian b69546c229 [GL backend] fix sampler binding bug
When a program had an unused SamplerInterfaceBlock, other samplers
could be bound to the wrong TMU

Fixes #5088
2022-01-25 10:09:22 -08:00
Alexey Pelykh 45054eece9 gltfio: support material extras 2022-01-25 10:04:10 -08:00
Philip Rideout 785f7de25d RangeMap: improve naming convention, etc. 2022-01-25 09:58:53 -08:00
Philip Rideout 509fb4ad23 RangeMap: improve the auto-merge functionality. 2022-01-25 09:58:53 -08:00
Philip Rideout 6577519bd7 utils: introduce RangeMap container and unit test.
This will allow the Vulkan backend to efficiently track the subresource
image layouts for each texture.

This is a sparse container for a series of ordered non-overlapping
integer intervals, where each interval maps to a concrete value.
2022-01-25 09:58:53 -08:00
Philip Rideout 43948421d7 Re-generate BlueVK and update to latest Vk headers.
Fixes #5026.
2022-01-25 09:14:23 -08:00
Philip Rideout 328650df17 BlueVK: Do not double initialize vkGetInstanceProcAddr.
This fixes a double-initialization problem for one of the function
pointers, and also updates the BlueVK generator to fix issues with the
latest Khronos XML file.

The corollary C++ changes will be made in a subsequent PR since they
will be difficult to review.

See #5026.
2022-01-24 13:40:49 -08:00
Benjamin Doherty b657ccd75a Release Filament 1.17.0 2022-01-24 12:48:28 -08:00
Ondrej Stava 11cbb3d395 Fixed VulkanTexture::copyBufferToImage for 2D texture arrays
2D array textures are initialized with .depth = 1 and layerCount = depth (see line 58 in VulkanTexture.cpp). By setting layerCount = 1 only the first layer was copied over, leaving the other layers uninitialized.
2022-01-24 10:38:03 -08:00
Mathias Agopian c21d7c3f5e try to use the Variant type instead of uint8_t everywhere 2022-01-24 09:45:34 -08:00
Philip Rideout 975665c9c9 gltf_viewer: fix the "Export screenshot" checkbox.
This functionality (in the Automation section) was violating a
constraint that was landed in November.

1) Call postRender inside beginFrame / endFrame.

2) Use RGBA when issuing ReadPixels (required by some backends) and
   convert to RGB when dumping out the PPM file.
2022-01-24 08:32:29 -08:00
daemyung jang 613e1052c7 Make morphable entities selectable in UI 2022-01-21 16:18:19 -08:00
Mathias Agopian ba9e7fa17f Improve (again) comments in Variants.h
- Improved formating
- Added more compile-time sanity checks
- Renamed Variant bits to 3 letters
2022-01-21 14:24:24 -08:00
daemyung jang fa54bdd682 Update imgui to v1.86 2022-01-21 09:53:44 -08:00
Mathias Agopian 1678d02c87 Allow more flexible quality settings for the ColorGrading LUT 2022-01-20 09:55:16 -08:00
daemyung jang 5e535165a6 Get morph target names from FilamentAsset (#5066)
Get morph target names from FilamentAsset
Make morphable entities selectable in UI
2022-01-19 17:11:24 -08:00
Mathias Agopian 3de427b74f Fix integration of screen-space reflections with lighting
screen-space reflections are integrated in the indirect light computation
(similarly to screen-space refraction), this is because it can be seen as
the specular term of screen-space GI.

However, because this effect is screen-space, the data it accesses has 
the ibl luminance (and exposure) applied.

Besides some minor refactoring, this change just applies the 
screen-space reflections *after* the ibl's specular term is exposed.
2022-01-19 17:10:10 -08:00
Mathias Agopian 15899af7cf randomly jitter the ray with screen-space reflections
this helps a lot when stride is > 1
2022-01-19 17:09:54 -08:00
daemyung jang 443181c719 Enhance code readability 2022-01-19 15:54:08 -08:00
daemyung jang 02f96e2a1e Store morph weight buffer at PrimitiveInfo to avoid dereference 2022-01-19 15:54:08 -08:00
daemyung jang 67e0aa5488 Store morph target buffer at PrimitiveInfo to avoid dereference 2022-01-19 15:54:08 -08:00
daemyung jang c969005bcc Create and bind morphing buffer if skinning is enabled
The morphing buffer is needed even if skinning is enabled
because shader is generated by HAS_SKINNING_OR_MORPHING.
2022-01-19 15:54:08 -08:00
Mathias Agopian 5417d0953b Allow screen space refraction and reflection together
We can now do screen-space refraction and reflections at the same time.
This change mostly removes the checks that were preventing it from
working.

The real change in the PR is to adjust the reprojection matrix based
on whether the SSR buffer (both for refractions and reflections) comes
from this or the previous frame.
2022-01-19 13:30:12 -08:00
Mathias Agopian ddb4865ceb allow a scene to have both transmission and reflection
what's not allowed at this point is an object which has both screen
space refraction and reflection.

this is accomplished by just always disabling screen-space reflections
for the translucent step of the refraction pass.
2022-01-19 13:30:12 -08:00
Philip Rideout 7b5cac6d4f Do not include <algorithm> unless necessary. 2022-01-19 13:11:04 -08:00
Ben Doherty fb76f8ed80 Add Java / WebGL bindings for screen-space reflections (#5054) 2022-01-19 12:50:32 -08:00
daemyung jang 4b572cf065 Remove duplicated APIs 2022-01-19 09:55:59 -08:00
daemyung jang 3e3fc76688 Add FilamentAsset Java bindings 2022-01-19 09:55:59 -08:00
Romain Guy 700b4d5d38 Update docs and readmes 2022-01-18 16:54:31 -08:00
daemyung jang 9e29d042b9 Add a comment for further work 2022-01-18 16:53:04 -08:00
daemyung jang 13f3ebca89 Transition the initial image layout if TextureUsage::SAMPLEABLE 2022-01-18 16:53:04 -08:00
Philip Rideout 3e30632b8c Reduce cascade of run-time warnings.
The `uint8_t` here needs to be cast to an integer to be printed
correctly. Also these warnings seem to be quite common so we should
hide them in Release builds.

These warnings probably indicate an actual problem that I do not fully
understand yet.
2022-01-18 16:04:16 -08:00
2270 changed files with 348744 additions and 316598 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ jobs:
build-windows:
name: build-windows
runs-on: windows-latest
runs-on: windows-2019
steps:
- uses: actions/checkout@v2.0.0
+5 -10
View File
@@ -50,8 +50,7 @@ jobs:
cd build/$WORKFLOW_OS && printf "y" | ./build.sh release
- name: Upload release assets
run: |
pip3 install setuptools
pip3 install PyGithub
xargs -L 1 sudo pip3 install < build/common/requirements.txt
if [ -f out/filament-release-darwin.tgz ]; then mv out/filament-release-darwin.tgz out/filament-${TAG}-mac.tgz; fi;
if [ -f out/filament-release-linux.tgz ]; then mv out/filament-release-linux.tgz out/filament-${TAG}-linux.tgz; fi;
python3 build/common/upload-assets.py ${TAG} out/*.tgz
@@ -80,8 +79,7 @@ jobs:
cd build/web && printf "y" | ./build.sh release
- name: Upload release assets
run: |
pip3 install setuptools
pip3 install PyGithub
xargs -L 1 sudo pip3 install < build/common/requirements.txt
mv out/filament-release-web.tgz out/filament-${TAG}-web.tgz
python3 build/common/upload-assets.py ${TAG} out/*.tgz
env:
@@ -123,15 +121,13 @@ jobs:
APK_KEYSTORE_PASS: ${{ secrets.APK_KEYSTORE_PASS }}
- name: Upload release assets
run: |
pip3 install setuptools
pip3 install PyGithub
xargs -L 1 sudo pip3 install < build/common/requirements.txt
mv out/filament-android-release.aar out/filament-${TAG}-android.aar
mv out/filamat-android-release.aar out/filamat-${TAG}-android.aar
mv out/filamat-android-lite-release.aar out/filamat-${TAG}-lite-android.aar
mv out/gltfio-android-release.aar out/gltfio-${TAG}-android.aar
mv out/gltfio-android-lite-release.aar out/gltfio-${TAG}-lite-android.aar
mv out/filament-utils-android-release.aar out/filament-utils-${TAG}-android.aar
mv out/filament-utils-android-lite-release.aar out/filament-utils-${TAG}-lite-android.aar
python3 build/common/upload-assets.py ${TAG} out/*.aar out/*.apk
env:
TAG: ${{ steps.git_ref.outputs.tag }}
@@ -158,8 +154,7 @@ jobs:
cd build/ios && printf "y" | ./build.sh release
- name: Upload release assets
run: |
pip3 install setuptools
pip3 install PyGithub
xargs -L 1 sudo pip3 install < build/common/requirements.txt
mv out/filament-release-ios.tgz out/filament-${TAG}-ios.tgz
python3 build/common/upload-assets.py ${TAG} out/*.tgz
env:
@@ -168,7 +163,7 @@ jobs:
build-windows:
name: build-windows
runs-on: windows-latest
runs-on: windows-2019
if: github.event_name == 'release' || github.event.inputs.platform == 'windows'
steps:
+1 -1
View File
@@ -10,7 +10,7 @@ on:
jobs:
build-windows:
name: build-windows
runs-on: windows-latest
runs-on: windows-2019
steps:
- uses: actions/checkout@v2.0.0
+1 -1
View File
@@ -349,7 +349,7 @@ same version that our continuous builds use.
```
cd <your chosen parent folder for the emscripten SDK>
curl -L https://github.com/emscripten-core/emsdk/archive/2.0.23.zip > emsdk.zip
curl -L https://github.com/emscripten-core/emsdk/archive/refs/tags/3.1.9.zip > emsdk.zip
unzip emsdk.zip ; mv emsdk-* emsdk ; cd emsdk
python ./emsdk.py install latest
python ./emsdk.py activate latest
+3 -3
View File
@@ -268,7 +268,7 @@ if (MSVC)
set(CXX_STANDARD "/std:c++latest")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD} /W0 /Zc:__cplusplus")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD} -fstrict-aliasing -Wno-unknown-pragmas -Wno-unused-function")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD} -fstrict-aliasing -Wno-unknown-pragmas -Wno-unused-function -Wno-deprecated-declarations")
endif()
if (FILAMENT_USE_EXTERNAL_GLES3)
@@ -647,12 +647,14 @@ add_subdirectory(${LIBRARIES}/gltfio)
add_subdirectory(${LIBRARIES}/ibl)
add_subdirectory(${LIBRARIES}/iblprefilter)
add_subdirectory(${LIBRARIES}/image)
add_subdirectory(${LIBRARIES}/ktxreader)
add_subdirectory(${LIBRARIES}/math)
add_subdirectory(${LIBRARIES}/mathio)
add_subdirectory(${LIBRARIES}/utils)
add_subdirectory(${LIBRARIES}/viewer)
add_subdirectory(${FILAMENT}/filament)
add_subdirectory(${FILAMENT}/shaders)
add_subdirectory(${EXTERNAL}/basisu/tnt)
add_subdirectory(${EXTERNAL}/civetweb/tnt)
add_subdirectory(${EXTERNAL}/hat-trie/tnt)
add_subdirectory(${EXTERNAL}/imgui/tnt)
@@ -705,8 +707,6 @@ if (IS_HOST_PLATFORM)
add_subdirectory(${FILAMENT}/samples)
add_subdirectory(${EXTERNAL}/astcenc/tnt)
add_subdirectory(${EXTERNAL}/etc2comp)
add_subdirectory(${EXTERNAL}/libassimp/tnt)
add_subdirectory(${EXTERNAL}/libpng/tnt)
add_subdirectory(${EXTERNAL}/libsdl2/tnt)
+7 -4
View File
@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.16.1'
implementation 'com.google.android.filament:filament-android:1.21.3'
}
```
@@ -43,7 +43,6 @@ Here are all the libraries available in the group `com.google.android.filament`:
| [![gltfio-android](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/gltfio-android/badge.svg?subject=gltfio-android)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/gltfio-android) | A glTF 2.0 loader for Filament, depends on `filament-android`. |
| [![gltfio-android-lite](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/gltfio-android-lite/badge.svg?subject=gltfio-android-lite)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/gltfio-android-lite) | Trimmed version of `gltfio` that does not support some glTF extensions. |
| [![filament-utils-android](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-utils-android/badge.svg?subject=filament-utils-android)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-utils-android) | KTX loading, Kotlin math, and camera utilities, depends on `gltfio-android`. |
| [![filament-utils-android-lite](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-utils-android-lite/badge.svg?subject=filament-utils-lite)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filament-utils-android-lite) | Trimmed version of `filament-utils` that does not support some glTF features. |
| [![filamat-android](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android/badge.svg?subject=filamat-android)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android) | A runtime material builder/compiler. This library is large but contains a full shader compiler/validator/optimizer and supports both OpenGL and Vulkan. |
| [![filamat-android-lite](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android-lite/badge.svg?subject=filamat-android-lite)](https://maven-badges.herokuapp.com/maven-central/com.google.android.filament/filamat-android-lite) | A much smaller alternative to `filamat-android` that can only generate OpenGL shaders. It does not provide validation or optimizations. |
@@ -52,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:
```
pod 'Filament', '~> 1.16.1'
pod 'Filament', '~> 1.21.3'
```
### Snapshots
@@ -63,7 +62,7 @@ steps:
1. Find the [commit](https://github.com/google/filament/commits/main) you're interested in.
2. Click the green check mark under the commit message.
3. Click on the _Details_ link for the platform you're interested in.
4. On the top right, click on the _Artifacts_ dropdown and choose an artifact.
4. On the top left click _Summary_, then in the _Artifacts_ section choose the desired artifact.
## Documentation
@@ -126,6 +125,7 @@ steps:
- Transparent shadows
- Contact shadows
- Screen-space ambient occlusion
- Screen-space reflections
- Screen-space refraction
- Global fog
- Dynamic resolution (with support for AMD FidelityFX FSR)
@@ -168,13 +168,16 @@ steps:
- [x] KHR_draco_mesh_compression
- [x] KHR_lights_punctual
- [x] KHR_materials_clearcoat
- [x] KHR_materials_emissive_strength
- [x] KHR_materials_ior
- [x] KHR_materials_pbrSpecularGlossiness
- [x] KHR_materials_sheen
- [x] KHR_materials_transmission
- [x] KHR_materials_unlit
- [x] KHR_materials_variants
- [x] KHR_materials_volume
- [x] KHR_mesh_quantization
- [x] KHR_texture_basisu
- [x] KHR_texture_transform
+117 -8
View File
@@ -3,12 +3,121 @@
This file contains one line summaries of commits that are worthy of mentioning in release notes.
A new header is inserted each time a *tag* is created.
## v1.17.1 (currently main branch)
## v1.22.1 (currently main branch)
## v1.22.0
- engine: Changed UBOs layout [⚠️ **Material breakage**].
- engine: Improve effects relying on mipmapping
## v1.21.3
- Java: Renamed the `KTXLoader` Kotlin class to `KTX1Loader`. [⚠️ **API Change**].
- libs: Added `Ktx2Reader` and `BasisEncoder` to support Basis-encoded KTX2 files.
- engine: Remove deprecated `Stream` APIs, see `Texture::import()` for an alternative [⚠️ **API Change**].
- tools: Removed KTX1 compression support from mipgen. [⚠️ **API Change**].
- tools: Added support for KTX2 to mipgen.
- gltfio: Added `resetBoneMatrices()` method.
- gltfio: Introduced `TextureProvider` interface. [⚠️ **API Change**].
- gltfio: Fix progress indicator when error occurs.
- samples: Desktop and Web Suzanne samples now use KTX2 instead of KTX1.
- samples: Fix regression with sample-gltf-viewer and zip files.
## v1.21.2
- Java: Add Java binding to get skins in `FilamentAsset`.
- libs: Add libs/ktxreader [⚠️ **API Change**].
- mipgen: fixups / clarification regarding sRGB.
- WebGL: fix intermittent 'detached ArrayBuffer' errors.
## v1.21.1
- engine: Allow both screen-space refraction and screen-space reflections on the same object [⚠️ **Material breakage**].
- engine: Optimizations for screen-space reflections.
- engine: Remove `Viewport::scale()` [⚠️ **API Change**].
- engine: Fix 12x overallocation of memory in `MorphTargetBuffer`.
- Metal: Fix validation error when reading from default `SwapChain`.
## v1.21.0
- engine: OpenGL performance improvements with some drivers.
- engine: Fix incorrect shadows with some custom projection matrices.
- engine: Fix low frame rates seen with a lot of morph targets.
- gltfio: Add support for KHR_materials_variants.
- gltfio: Add support for KHR_materials_emissive_strength.
- gltfio: Java now exposes morph target names as an array for consistency [⚠️ **API Change**].
## v1.20.5
- engine: New behavior for MASKED to work with translucent views. [⚠️ **Recompile Materials** to get the fix]
- engine: Fix screen-space reflections when post-processing and MSAA are off.
- engine: Update MAX_MORPH_TARGETS constant to 256.
- engine: Fix point light lighting with ortho projection.
- libs: BlueGL symbols are now prefixed with `bluegl` on all platforms.
- gltfio: Add skinning getters to `FilamentAsset`.
## v1.20.4
- gltfio: Java clients must now destroy the MaterialProvider [⚠️ **API Change**].
- gltfio: Fix, bone pose not applied if glTF model doesn't have animations.
- libs: Added `math::quat::fromDirectedRotation` [**NEW API**].
- WebGL: Restore GL state when frame ends.
## v1.20.3
- Java: Fix URI bug in Android Viewer sample when dropping some zips.
- Vulkan: Fix "uninitialized texture" warnings from the Vulkan backend.
## v1.20.2
- engine: Binary size optimizations.
- engine: Fix, Mat4 from Quaternion was transposed.
- Vulkan: Internal bug fixes and robustness improvements.
- Vulkan: Reduced log spam.
## v1.20.1
- engine: Binary size improvements.
- engine: Add basic support for instanced renderables [**NEW API**].
- engine: Fix, first imaged passsed to `Stream::SetAcquiredImage` is ignored and leaked.
- Vulkan: Robustness improvements.
- Java: Fix, lookAt z axis negated.
- gltfio: Be graceful when model has > 4 weights per vert.
## v1.20.0
- engine: Support rough screen-space reflections [⚠️ **Material breakage**].
- engine: Added `Scene::forEach` API to iterate through a scene's entities.
- engine: Fix incorrect normals with skinned models.
- Vulkan: Fix segfault during shutdown.
- WebGL: Support web apps that have multiple `FilamentViewer`s.
- gltfio: Performance enhancements when loading models.
## v1.19.0
- engine: Support 256 morph targets.
- engine: Screen-space reflection improvements.
- engine: Morphing improvements and bug fixes.
- gltfio: Generate morphing normals when they are missing.
- gltfio: Support material extras.
- Java: Add bindings for new morphing API.
- Vulkan: Fix segfault on macOS.
## v1.18.0
- engine: Add support separate samplers in fragment and vertex shaders [⚠️ **Material breakage**].
- engine: Support legacy morphing mode with vertex attributes.
- engine: Allow more flexible quality settings for the ColorGrading LUT.
- engine: Improve screen-space reflections quality and allow reflections and refractions together.
- Vulkan: Bug fixes and improvements.
## v1.17.0
- engine: add experimental glossy screen-space reflections [⚠️ **Materials need to be rebuilt to
access this new feature**].
- engine: Add experimental glossy screen-space reflections.
- engine: Add support for GPU morphing and 128 morph targets.
- engine: Fix crash with non-shadow receiving renderables and VSM.
- engine: Bring back the 3x3 filter for PCF shadows.
- engine: Correct AABB calculation for skinned glTF models.
## v1.16.1
@@ -24,10 +133,10 @@ A new header is inserted each time a *tag* is created.
## v1.15.2
- engine: add support for PCSS (Percentage Closer Soft Shadows).
- engine: fix spotlight shadow bias.
- samples: avoid leaking IBLs in Android sample-gltf-viewer.
- libs: fix `libibl` on mobile.
- engine: Add support for PCSS (Percentage Closer Soft Shadows).
- engine: Fix spotlight shadow bias.
- samples: Avoid leaking IBLs in Android sample-gltf-viewer.
- libs: Fix `libibl` on mobile.
## v1.15.1
@@ -362,7 +471,7 @@ devices.
- engine: Fix RenderTarget NPE when depth is not present.
- engine: Improvements to Camera APIs. Move focus distance from DofOptions to Camera.
- engine: VSM shadows now support `shadowMultiplier`.
- java: Expose severla MaterialInstance APIs (setColorWrite, setDepthWrite, setDepthCulling) that
- java: Expose several MaterialInstance APIs (setColorWrite, setDepthWrite, setDepthCulling) that
should have been public.
- java: fix bug with Texture::setImage buffer size calculation.
+16 -6
View File
@@ -11,6 +11,9 @@
// com.google.android.filament.exclude-vulkan
// When set, support for Vulkan will be excluded.
//
// com.google.android.filament.matdbg
// When set, enables matdbg, disables shader optimizations
//
// com.google.android.filament.skip-samples
// Exclude samples from the project. Useful to speed up compilation.
//
@@ -59,6 +62,11 @@ buildscript {
.forUseAtConfigurationTime()
.isPresent()
def matdbg = providers
.gradleProperty("com.google.android.filament.matdbg")
.forUseAtConfigurationTime()
.isPresent()
def abis = ["arm64-v8a", "armeabi-v7a", "x86_64", "x86"]
def newAbis = providers
.gradleProperty("com.google.android.filament.abis")
@@ -73,9 +81,9 @@ buildscript {
'minSdk': 19,
'targetSdk': 31,
'compileSdk': 31,
'kotlin': '1.6.0',
'kotlin_coroutines': '1.5.2',
'buildTools': '31.0.0',
'kotlin': '1.6.10',
'kotlin_coroutines': '1.6.0',
'buildTools': '32.0.0',
'ndk': '23.1.7779620'
]
@@ -92,8 +100,8 @@ buildscript {
]
dependencies {
// NOTE: See TODO in gradle.properties once we move to Gradle 7.2
classpath 'com.android.tools.build:gradle:7.0.3'
// NOTE: See TODO in gradle.properties once we move to Gradle 7.4
classpath 'com.android.tools.build:gradle:7.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
}
@@ -102,7 +110,9 @@ buildscript {
"-DANDROID_PLATFORM=21",
"-DANDROID_STL=c++_static",
"-DFILAMENT_DIST_DIR=${filamentPath}".toString(),
"-DFILAMENT_SUPPORTS_VULKAN=${excludeVulkan ? 'OFF' : 'ON'}".toString()
"-DFILAMENT_SUPPORTS_VULKAN=${excludeVulkan ? 'OFF' : 'ON'}".toString(),
"-DFILAMENT_ENABLE_MATDBG=${matdbg ? 'ON' : 'OFF'}".toString(),
"-DFILAMENT_DISABLE_MATOPT=${matdbg ? 'ON' : 'OFF'}".toString()
]
ext.cppFlags = [
@@ -370,3 +370,10 @@ Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderVariant
auto builder = (MaterialBuilder*) nativeBuilder;
builder->variantFilter((uint8_t) variantFilter);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderUseLegacyMorphing(JNIEnv*,
jclass, jlong nativeBuilder) {
auto builder = (MaterialBuilder*) nativeBuilder;
builder->useLegacyMorphing();
}
@@ -114,14 +114,14 @@ public class MaterialBuilder {
BONE_INDICES, // indices of 4 bones (uvec4)
BONE_WEIGHTS, // weights of the 4 bones (normalized float4)
UNUSED, // reserved for future use
CUSTOM0, // custom
CUSTOM1, // custom
CUSTOM2, // custom
CUSTOM3, // custom
CUSTOM4, // custom
CUSTOM5, // custom
CUSTOM6, // custom
CUSTOM7 // custom
CUSTOM0, // custom or MORPH_POSITION_0
CUSTOM1, // custom or MORPH_POSITION_1
CUSTOM2, // custom or MORPH_POSITION_2
CUSTOM3, // custom or MORPH_POSITION_3
CUSTOM4, // custom or MORPH_TANGENTS_0
CUSTOM5, // custom or MORPH_TANGENTS_1
CUSTOM6, // custom or MORPH_TANGENTS_2
CUSTOM7 // custom or MORPH_TANGENTS_3
}
public enum BlendingMode {
@@ -133,7 +133,7 @@ public class MaterialBuilder {
FADE, // material is transparent and color is alpha-pre-multiplied,
// affects specular lighting
MULTIPLY, // material darkens what's behind it
SCREN // material brightens what's behind it
SCREEN // material brightens what's behind it
}
public enum VertexDomain {
@@ -459,6 +459,19 @@ public class MaterialBuilder {
@NonNull
public MaterialBuilder variantFilter(int variantFilter) {
nMaterialBuilderVariantFilter(mNativeObject, variantFilter);
useLegacyMorphing();
return this;
}
/**
* Legacy morphing uses the data in the {@link VertexBuffer.VertexAttribute} slots
* (<code>MORPH_POSITION_0</code>, etc) and is limited to 4 morph targets.
*
* @see RenderableManager.Builder#morphing()
*/
@NonNull
public MaterialBuilder useLegacyMorphing() {
nMaterialBuilderUseLegacyMorphing(mNativeObject);
return this;
}
@@ -599,4 +612,5 @@ public class MaterialBuilder {
private static native void nMaterialBuilderOptimization(long nativeBuilder, int optimization);
private static native void nMaterialBuilderVariantFilter(long nativeBuilder,
int variantFilter);
private static native void nMaterialBuilderUseLegacyMorphing(long nativeBuilder);
}
+1
View File
@@ -74,6 +74,7 @@ add_library(filament-jni SHARED
src/main/cpp/Material.cpp
src/main/cpp/MaterialInstance.cpp
src/main/cpp/MathUtils.cpp
src/main/cpp/MorphTargetBuffer.cpp
src/main/cpp/RenderableManager.cpp
src/main/cpp/Renderer.cpp
src/main/cpp/RenderTarget.cpp
@@ -50,6 +50,19 @@ Java_com_google_android_filament_ColorGrading_nBuilderQuality(JNIEnv*, jclass, j
builder->quality(quality);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_ColorGrading_nBuilderFormat(JNIEnv*, jclass, jlong nativeBuilder, jint format_) {
ColorGrading::Builder* builder = (ColorGrading::Builder*) nativeBuilder;
ColorGrading::LutFormat format = (ColorGrading::LutFormat) format_;
builder->format(format);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_ColorGrading_nBuilderDimensions(JNIEnv*, jclass, jlong nativeBuilder, jint dim_) {
ColorGrading::Builder* builder = (ColorGrading::Builder*) nativeBuilder;
builder->dimensions((uint8_t)dim_);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_ColorGrading_nBuilderToneMapper(JNIEnv*, jclass,
jlong nativeBuilder, jlong toneMapper_) {
@@ -0,0 +1,114 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <functional>
#include <stdlib.h>
#include <string.h>
#include <filament/MorphTargetBuffer.h>
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"
using namespace filament;
using namespace backend;
extern "C"
JNIEXPORT jlong JNICALL
Java_com_google_android_filament_MorphTargetBuffer_nCreateBuilder(JNIEnv*, jclass) {
return (jlong) new MorphTargetBuffer::Builder();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MorphTargetBuffer_nDestroyBuilder(JNIEnv*, jclass,
jlong nativeBuilder) {
MorphTargetBuffer::Builder* builder = (MorphTargetBuffer::Builder *) nativeBuilder;
delete builder;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MorphTargetBuffer_nBuilderVertexCount(JNIEnv*, jclass,
jlong nativeBuilder, jint vertexCount) {
MorphTargetBuffer::Builder* builder = (MorphTargetBuffer::Builder *) nativeBuilder;
builder->vertexCount((size_t) vertexCount);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MorphTargetBuffer_nBuilderCount(JNIEnv*, jclass,
jlong nativeBuilder, jint count) {
MorphTargetBuffer::Builder* builder = (MorphTargetBuffer::Builder *) nativeBuilder;
builder->count((size_t) count);
}
extern "C"
JNIEXPORT jlong JNICALL
Java_com_google_android_filament_MorphTargetBuffer_nBuilderBuild(JNIEnv*, jclass,
jlong nativeBuilder, jlong nativeEngine) {
MorphTargetBuffer::Builder* builder = (MorphTargetBuffer::Builder *) nativeBuilder;
Engine *engine = (Engine *) nativeEngine;
return (jlong) builder->build(*engine);
}
// ------------------------------------------------------------------------------------------------
extern "C"
JNIEXPORT jint JNICALL
Java_com_google_android_filament_MorphTargetBuffer_nSetPositionsAt(JNIEnv* env, jclass,
jlong nativeObject, jlong nativeEngine,
jint targetIndex, jfloatArray positions, jint count) {
MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeObject;
Engine *engine = (Engine *) nativeEngine;
jfloat* data = env->GetFloatArrayElements(positions, NULL);
morphTargetBuffer->setPositionsAt(*engine, targetIndex,
(math::float4*) data, size_t(count));
env->ReleaseFloatArrayElements(positions, data, JNI_ABORT);
return 0;
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_google_android_filament_MorphTargetBuffer_nSetTangentsAt(JNIEnv* env, jclass,
jlong nativeObject, jlong nativeEngine,
jint targetIndex, jshortArray tangents, jint count) {
MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeObject;
Engine *engine = (Engine *) nativeEngine;
jshort* data = env->GetShortArrayElements(tangents, NULL);
morphTargetBuffer->setTangentsAt(*engine, targetIndex,
(math::short4*) data, size_t(count));
env->ReleaseShortArrayElements(tangents, data, JNI_ABORT);
return 0;
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_google_android_filament_MorphTargetBuffer_nGetVertexCount(JNIEnv*, jclass,
jlong nativeObject) {
MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeObject;
return (jint)morphTargetBuffer->getVertexCount();
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_google_android_filament_MorphTargetBuffer_nGetCount(JNIEnv*, jclass,
jlong nativeObject) {
MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeObject;
return (jint)morphTargetBuffer->getCount();
}
@@ -209,9 +209,18 @@ Java_com_google_android_filament_RenderableManager_nBuilderSkinningBones(JNIEnv*
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderMorphing(JNIEnv*, jclass,
jlong nativeBuilder, jboolean enabled) {
jlong nativeBuilder, jint targetCount) {
RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
builder->morphing(enabled);
builder->morphing(targetCount);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderSetMorphTargetBufferAt(JNIEnv*, jclass,
jlong nativeBuilder, int level, int primitiveIndex, jlong nativeMorphTargetBuffer,
int offset, int count) {
RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeMorphTargetBuffer;
builder->morphing(level, primitiveIndex, morphTargetBuffer, offset, count);
}
extern "C" JNIEXPORT void JNICALL
@@ -221,6 +230,13 @@ Java_com_google_android_filament_RenderableManager_nBuilderLightChannel(JNIEnv*,
builder->lightChannel(channel, (bool)enable);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderInstances(JNIEnv*, jclass,
jlong nativeBuilder, jint instanceCount) {
RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
builder->instances(instanceCount);
}
// ------------------------------------------------------------------------------------------------
extern "C" JNIEXPORT void JNICALL
@@ -267,14 +283,31 @@ Java_com_google_android_filament_RenderableManager_nSetBonesAsQuaternions(JNIEnv
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetMorphWeights(JNIEnv* env, jclass,
jlong nativeRenderableManager, jint instance, jfloatArray weights) {
jlong nativeRenderableManager, jint instance, jfloatArray weights, jint offset) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
jfloat* vec = env->GetFloatArrayElements(weights, NULL);
jsize count = env->GetArrayLength(weights);
rm->setMorphWeights((RenderableManager::Instance)instance, vec, count);
rm->setMorphWeights((RenderableManager::Instance)instance, vec, count, offset);
env->ReleaseFloatArrayElements(weights, vec, JNI_ABORT);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetMorphTargetBufferAt(JNIEnv*,
jclass, jlong nativeRenderableManager, jint i, int level, jint primitiveIndex,
jlong nativeMorphTargetBuffer, jint offset, jint count) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeMorphTargetBuffer;
rm->setMorphTargetBufferAt((RenderableManager::Instance) i, (uint8_t) level,
(size_t) primitiveIndex, morphTargetBuffer, (size_t) offset, (size_t) count);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_RenderableManager_nGetMorphTargetCount(JNIEnv* env, jclass,
jlong nativeRenderableManager, jint instance) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
return rm->getMorphTargetCount((RenderableManager::Instance)instance);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetAxisAlignedBoundingBox(JNIEnv*,
jclass, jlong nativeRenderableManager, jint i, jfloat cx, jfloat cy, jfloat cz,
@@ -98,16 +98,6 @@ Java_com_google_android_filament_Stream_nBuilderStreamSource(JNIEnv* env,
builder->setStreamSource(env, streamSource);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Stream_nBuilderStream(JNIEnv*, jclass,
jlong nativeStreamBuilder, jlong externalTextureId) {
StreamBuilder* builder = (StreamBuilder*) nativeStreamBuilder;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
builder->builder()->stream(externalTextureId);
#pragma clang diagnostic pop
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Stream_nBuilderWidth(JNIEnv*, jclass,
jlong nativeStreamBuilder, jint width) {
@@ -143,41 +133,6 @@ Java_com_google_android_filament_Stream_nSetDimensions(JNIEnv*, jclass, jlong na
stream->setDimensions((uint32_t) width, (uint32_t) height);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_Stream_nReadPixels(JNIEnv *env, jclass,
jlong nativeStream, jlong nativeEngine,
jint xoffset, jint yoffset, jint width, jint height,
jobject storage, jint remaining,
jint left, jint top, jint type, jint alignment, jint stride, jint format,
jobject handler, jobject runnable) {
Stream *stream = (Stream *) nativeStream;
Engine *engine = (Engine *) nativeEngine;
stride = stride ? stride : width;
size_t sizeInBytes = PixelBufferDescriptor::computeDataSize(
(PixelDataFormat) format, (PixelDataType) type,
(size_t) stride, (size_t) (height + top), (size_t) alignment);
AutoBuffer nioBuffer(env, storage, 0);
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
// BufferOverflowException
return -1;
}
void *buffer = nioBuffer.getData();
auto *callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
(uint32_t) stride,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
stream->readPixels(uint32_t(xoffset), uint32_t(yoffset), uint32_t(width), uint32_t(height),
std::move(desc));
return 0;
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Stream_nGetTimestamp(JNIEnv*, jclass, jlong nativeStream) {
Stream *stream = (Stream *) nativeStream;
@@ -201,8 +156,8 @@ Java_com_google_android_filament_Stream_nSetAcquiredImage(JNIEnv* env, jclass, j
if (!AHardwareBuffer_fromHardwareBuffer_fn) {
__android_log_print(ANDROID_LOG_WARN, "Filament", "AHardwareBuffer_fromHardwareBuffer is not available.");
sHardwareBufferSupported = false;
return;
}
return;
}
AHardwareBuffer* nativeBuffer = AHardwareBuffer_fromHardwareBuffer_fn(env, hwbuffer);
@@ -390,6 +390,16 @@ Java_com_google_android_filament_View_nSetTemporalAntiAliasingOptions(JNIEnv *,
.filterWidth = filterWidth, .feedback = feedback, .enabled = (bool) enabled});
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetScreenSpaceReflectionsOptions(JNIEnv*, jclass,
jlong nativeView, jfloat thickness, jfloat bias, jfloat maxDistance, jfloat stride, jboolean enabled) {
View* view = (View*) nativeView;
view->setScreenSpaceReflectionsOptions({.thickness = thickness, .bias = bias,
.maxDistance = maxDistance, .stride = stride, .enabled = (bool) enabled
});
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_View_nIsShadowingEnabled(JNIEnv *, jclass, jlong nativeView) {
@@ -105,6 +105,14 @@ public class ColorGrading {
ULTRA
}
/**
* Color grading LUT format.
*/
public enum LutFormat {
INTEGER,
FLOAT
}
/**
* List of available tone-mapping operators.
*
@@ -162,6 +170,36 @@ public class ColorGrading {
return this;
}
/**
* When color grading is implemented using a 3D LUT, this sets the texture format of
* of the LUT. This overrides the value set by quality().
*
* The default is INTEGER
*
* @param format The desired format of the 3D LUT.
*
* @return This Builder, for chaining calls
*/
public Builder format(LutFormat format) {
nBuilderFormat(mNativeBuilder, format.ordinal());
return this;
}
/**
* When color grading is implemented using a 3D LUT, this sets the dimension of the LUT.
* This overrides the value set by quality().
*
* The default is 32
*
* @param dim The desired dimension of the LUT. Between 16 and 64.
*
* @return This Builder, for chaining calls
*/
public Builder dimensions(int dim) {
nBuilderDimensions(mNativeBuilder, dim);
return this;
}
/**
* Selects the tone mapping operator to apply to the HDR color buffer as the last
* operation of the color grading post-processing step.
@@ -557,6 +595,8 @@ public class ColorGrading {
private static native void nDestroyBuilder(long nativeBuilder);
private static native void nBuilderQuality(long nativeBuilder, int quality);
private static native void nBuilderFormat(long nativeBuilder, int format);
private static native void nBuilderDimensions(long nativeBuilder, int dim);
private static native void nBuilderToneMapper(long nativeBuilder, long toneMapper);
private static native void nBuilderToneMapping(long nativeBuilder, int toneMapping);
private static native void nBuilderLuminanceScaling(long nativeBuilder, boolean luminanceScaling);
@@ -239,6 +239,10 @@ public class MaterialInstance {
/**
* Sets a texture and sampler parameter on this material's default instance.
* <p>
* Note: Depth textures can't be sampled with a linear filter unless the comparison mode is set
* to COMPARE_TO_TEXTURE.
* </p>
*
* @param name The name of the material texture parameter
* @param texture The texture to set as parameter
@@ -0,0 +1,177 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.filament;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import java.nio.Buffer;
import java.nio.BufferOverflowException;
import java.nio.FloatBuffer;
public class MorphTargetBuffer {
private long mNativeObject;
private MorphTargetBuffer(long nativeMorphTargetBuffer) {
mNativeObject = nativeMorphTargetBuffer;
}
public static class Builder {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
// Keep to finalize native resources
private final MorphTargetBuffer.Builder.BuilderFinalizer mFinalizer;
private final long mNativeBuilder;
public Builder() {
mNativeBuilder = nCreateBuilder();
mFinalizer = new MorphTargetBuffer.Builder.BuilderFinalizer(mNativeBuilder);
}
/**
* Size of the morph targets in vertex counts.
*
* @param vertexCount Number of vertex counts the morph targets can hold.
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder vertexCount(@IntRange(from = 1) int vertexCount) {
nBuilderVertexCount(mNativeBuilder, vertexCount);
return this;
}
/**
* Size of the morph targets in targets.
*
* @param count Number of targets the morph targets can hold.
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder count(@IntRange(from = 1) int count) {
nBuilderCount(mNativeBuilder, count);
return this;
}
/**
* Creates and returns the <code>MorphTargetBuffer</code> object.
*
* @param engine reference to the {@link Engine} to associate this <code>MorphTargetBuffer</code>
* with.
*
* @return the newly created <code>MorphTargetBuffer</code> object
*
* @exception IllegalStateException if the MorphTargetBuffer could not be created
*
* @see #setMorphTargetBufferAt
*/
@NonNull
public MorphTargetBuffer build(@NonNull Engine engine) {
long nativeMorphTargetBuffer = nBuilderBuild(mNativeBuilder, engine.getNativeObject());
if (nativeMorphTargetBuffer == 0)
throw new IllegalStateException("Couldn't create MorphTargetBuffer");
return new MorphTargetBuffer(nativeMorphTargetBuffer);
}
private static class BuilderFinalizer {
private final long mNativeObject;
BuilderFinalizer(long nativeObject) {
mNativeObject = nativeObject;
}
@Override
public void finalize() {
try {
super.finalize();
} catch (Throwable t) { // Ignore
} finally {
nDestroyBuilder(mNativeObject);
}
}
}
}
/**
* Updates positions of morph target at the index.
*
* @param engine {@link Engine} instance
* @param targetIndex The index of morph target to be updated
* @param positions Pointer to at least count positions
* @param count Number of position elements in positions
*/
public void setPositionsAt(@NonNull Engine engine,
@IntRange(from = 0) int targetIndex,
@NonNull float[] positions, @IntRange(from = 0, to = 125) int count) {
int result = nSetPositionsAt(mNativeObject, engine.getNativeObject(), targetIndex,
positions, count);
if (result < 0) {
throw new BufferOverflowException();
}
}
/**
* Updates tangents of morph target at the index.
*
* @param engine {@link Engine} instance
* @param targetIndex The index of morph target to be updated
* @param tangents Pointer to at least count tangents
* @param count Number of tangent elements in tangents
*/
public void setTangentsAt(@NonNull Engine engine,
@IntRange(from = 0) int targetIndex,
@NonNull short[] tangents, @IntRange(from = 0, to = 125) int count) {
int result = nSetTangentsAt(mNativeObject, engine.getNativeObject(), targetIndex,
tangents, count);
if (result < 0) {
throw new BufferOverflowException();
}
}
/**
* @return number of vertex count in this {@link MorphTargetBuffer}
*/
public int getVertexCount() {
return nGetVertexCount(mNativeObject);
}
/**
* @return number of target count in this {@link MorphTargetBuffer}
*/
public int getCount() {
return nGetCount(mNativeObject);
}
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed MorphTargetBuffer");
}
return mNativeObject;
}
void clearNativeObject() {
mNativeObject = 0;
}
private static native long nCreateBuilder();
private static native void nDestroyBuilder(long nativeBuilder);
private static native void nBuilderVertexCount(long nativeBuilder, int vertexCount);
private static native void nBuilderCount(long nativeBuilder, int count);
private static native long nBuilderBuild(long nativeBuilder, long nativeEngine);
private static native int nSetPositionsAt(long nativeObject, long nativeEngine, int targetIndex, float[] positions, int count);
private static native int nSetTangentsAt(long nativeObject, long nativeEngine, int targetIndex, short[] tangents, int count);
private static native int nGetVertexCount(long nativeObject);
private static native int nGetCount(long nativeObject);
}
@@ -284,6 +284,22 @@ public class RenderableManager {
return this;
}
/**
* Specifies the number of draw instance of this renderable. The default is 1 instance and
* the maximum number of instances allowed is 65535. 0 is invalid.
* All instances are culled using the same bounding box, so care must be taken to make
* sure all instances render inside the specified bounding box.
* The material can use getInstanceIndex() in the vertex shader to get the instance index and
* possibly adjust the position or transform.
*
* @param instanceCount the number of instances silently clamped between 1 and 65535.
*/
@NonNull
public Builder instances(@IntRange(from = 1, to = 65535) int instanceCount) {
nBuilderInstances(mNativeBuilder, instanceCount);
return this;
}
/**
* Controls if this renderable casts shadows, false by default.
*
@@ -400,14 +416,67 @@ public class RenderableManager {
}
/**
* Controls if the renderable has vertex morphing targets, false by default.
* Controls if the renderable has vertex morphing targets, zero by default. This is
* required to enable GPU morphing.
*
* <p>Filament supports two morphing modes: standard (default) and legacy.</p>
*
* <p>For standard morphing, A {@link MorphTargetBuffer} must be created and provided via
* {@link RenderableManager#setMorphTargetBufferAt}. Standard morphing supports up to
* <code>CONFIG_MAX_MORPH_TARGET_COUNT</code> morph targets.</p>
*
* For legacy morphing, the attached {@link VertexBuffer} must provide data in the
* appropriate {@link VertexBuffer.VertexAttribute} slots (<code>MORPH_POSITION_0</code> etc).
* Legacy morphing only supports up to 4 morph targets and will be deprecated in the future.
* Legacy morphing must be enabled on the material definition: either via the
* <code>legacyMorphing</code> material attribute or by calling
* {@link MaterialBuilder::useLegacyMorphing}.
*
* <p>See also {@link RenderableManager#setMorphWeights}, which can be called on a per-frame basis
* to advance the animation.</p>
*/
@NonNull
public Builder morphing(boolean enabled) {
nBuilderMorphing(mNativeBuilder, enabled);
public Builder morphing(@IntRange(from = 0, to = 255) int targetCount) {
nBuilderMorphing(mNativeBuilder, targetCount);
return this;
}
/**
* Specifies the morph target buffer for a primitive.
*
* The morph target buffer must have an associated renderable and geometry. Two conditions
* must be met:
* 1. The number of morph targets in the buffer must equal the renderable's morph target
* count.
* 2. The vertex count of each morph target must equal the geometry's vertex count.
*
* @param level the level of detail (lod), only 0 can be specified
* @param primitiveIndex zero-based index of the primitive, must be less than the count passed to Builder constructor
* @param morphTargetBuffer specifies the morph target buffer
* @param offset specifies where in the morph target buffer to start reading (expressed as a number of vertices)
* @param count number of vertices in the morph target buffer to read, must equal the geometry's count (for triangles, this should be a multiple of 3)
*/
@NonNull
public Builder morphing(@IntRange(from = 0) int level,
@IntRange(from = 0) int primitiveIndex,
@NonNull MorphTargetBuffer morphTargetBuffer,
@IntRange(from = 0) int offset,
@IntRange(from = 0) int count) {
nBuilderSetMorphTargetBufferAt(mNativeBuilder, level, primitiveIndex,
morphTargetBuffer.getNativeObject(), offset, count);
return this;
}
/**
* Utility method to specify morph target buffer for a primitive.
* For details, see the {@link RenderableManager.Builder#morphing}.
*/
@NonNull
public Builder morphing(@IntRange(from = 0) int level,
@IntRange(from = 0) int primitiveIndex,
@NonNull MorphTargetBuffer morphTargetBuffer) {
nBuilderSetMorphTargetBufferAt(mNativeBuilder, level, primitiveIndex,
morphTargetBuffer.getNativeObject(), 0, morphTargetBuffer.getVertexCount());
return this;
}
@@ -494,12 +563,50 @@ public class RenderableManager {
/**
* Updates the vertex morphing weights on a renderable, all zeroes by default.
*
* <p>The renderable must be built with morphing enabled. In legacy morphing mode, only the
* first 4 weights are considered.</p>
*
* @see Builder#morphing
*/
public void setMorphWeights(@EntityInstance int i, @NonNull float[] weights, @IntRange(from = 0) int offset) {
nSetMorphWeights(mNativeObject, i, weights, offset);
}
/**
* Changes the morph target buffer for the given primitive.
*
* <p>The renderable must be built with morphing enabled.</p>
*
* @see Builder#morphing
*/
public void setMorphWeights(@EntityInstance int i, @NonNull float[] weights) {
nSetMorphWeights(mNativeObject, i, weights);
public void setMorphTargetBufferAt(@EntityInstance int i,
@IntRange(from = 0) int level,
@IntRange(from = 0) int primitiveIndex,
@NonNull MorphTargetBuffer morphTargetBuffer,
@IntRange(from = 0) int offset,
@IntRange(from = 0) int count) {
nSetMorphTargetBufferAt(mNativeObject, i, level, primitiveIndex,
morphTargetBuffer.getNativeObject(), offset, count);
}
/**
* Utility method to change morph target buffer for the given primitive.
* For details, see the {@link RenderableManager#setMorphTargetBufferAt}.
*/
public void setMorphTargetBufferAt(@EntityInstance int i,
@IntRange(from = 0) int level,
@IntRange(from = 0) int primitiveIndex,
@NonNull MorphTargetBuffer morphTargetBuffer) {
nSetMorphTargetBufferAt(mNativeObject, i, level, primitiveIndex,
morphTargetBuffer.getNativeObject(), 0, morphTargetBuffer.getVertexCount());
}
/**
* Gets the morph target count on a renderable.
*/
@IntRange(from = 0)
public int getMorphTargetCount(@EntityInstance int i) {
return nGetMorphTargetCount(mNativeObject, i);
}
/**
@@ -756,14 +863,18 @@ public class RenderableManager {
private static native void nBuilderSkinning(long nativeBuilder, int boneCount);
private static native int nBuilderSkinningBones(long nativeBuilder, int boneCount, Buffer bones, int remaining);
private static native void nBuilderSkinningBuffer(long nativeBuilder, long nativeSkinningBuffer, int boneCount, int offset);
private static native void nBuilderMorphing(long nativeBuilder, boolean enabled);
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 nEnableSkinningBuffers(long nativeBuilder, boolean enabled);
private static native void nBuilderLightChannel(long nativeRenderableManager, int channel, boolean enable);
private static native void nBuilderInstances(long nativeRenderableManager, int instances);
private static native void nSetSkinningBuffer(long nativeObject, int i, long nativeSkinningBuffer, int count, int offset);
private static native int nSetBonesAsMatrices(long nativeObject, int i, Buffer matrices, int remaining, int boneCount, int offset);
private static native int nSetBonesAsQuaternions(long nativeObject, int i, Buffer quaternions, int remaining, int boneCount, int offset);
private static native void nSetMorphWeights(long nativeObject, int instance, float[] weights);
private static native void nSetMorphWeights(long nativeObject, int instance, float[] weights, int offset);
private static native void nSetMorphTargetBufferAt(long nativeObject, int i, int level, int primitiveIndex, long nativeMorphTargetBuffer, int offset, int count);
private static native int nGetMorphTargetCount(long nativeObject, int i);
private static native void nSetAxisAlignedBoundingBox(long nativeRenderableManager, int i, float cx, float cy, float cz, float ex, float ey, float ez);
private static native void nSetLayerMask(long nativeRenderableManager, int i, int select, int value);
private static native void nSetPriority(long nativeRenderableManager, int i, int priority);
@@ -531,6 +531,10 @@ public class Renderer {
* Typically, this will happen after multiple calls to {@link #beginFrame},
* {@link #render}, {@link #endFrame}.</p>
* <br>
* <p>OpenGL only: if issuing a <code>readPixels</code> on a {@link RenderTarget} backed by a
* {@link Texture} that had data uploaded to it via {@link Texture#setImage}, the data returned
* from <code>readPixels</code> will be y-flipped with respect to the {@link Texture#setImage}
* call.</p>
* <p><code>readPixels</code> is intended for debugging and testing.
* It will impact performance significantly.</p>
*
@@ -118,8 +118,8 @@ public class SkinningBuffer {
* @param offset Index of the first bone to set
*/
public void setBonesAsMatrices(@NonNull Engine engine,
@NonNull Buffer matrices, @IntRange(from = 0, to = 255) int boneCount,
@IntRange(from = 0) int offset) {
@NonNull Buffer matrices, @IntRange(from = 0, to = 255) int boneCount,
@IntRange(from = 0) int offset) {
int result = nSetBonesAsMatrices(mNativeObject, engine.getNativeObject(),
matrices, matrices.remaining(), boneCount, offset);
if (result < 0) {
@@ -138,8 +138,8 @@ public class SkinningBuffer {
* @param offset Index of the first bone to set
*/
public void setBonesAsQuaternions(@NonNull Engine engine,
@NonNull Buffer quaternions, @IntRange(from = 0, to = 255) int boneCount,
@IntRange(from = 0) int offset) {
@NonNull Buffer quaternions, @IntRange(from = 0, to = 255) int boneCount,
@IntRange(from = 0) int offset) {
int result = nSetBonesAsQuaternions(mNativeObject, engine.getNativeObject(),
quaternions, quaternions.remaining(), boneCount, offset);
if (result < 0) {
@@ -103,9 +103,6 @@ public class Stream {
/** Not synchronized but copy-free. Good for video. */
NATIVE,
/** Synchronized, but GL-only and incurs copies. Good for AR on devices before API 26. */
TEXTURE_ID,
/** Synchronized, copy-free, and take a release callback. Good for AR but requires API 26+. */
ACQUIRED,
};
@@ -121,7 +118,7 @@ public class Stream {
* By default, Stream objects are {@link StreamType#ACQUIRED ACQUIRED} and must have external images pushed to them via
* {@link #setAcquiredImage}.
*
* To create a {@link StreamType#NATIVE NATIVE} or {@link StreamType#TEXTURE_ID TEXTURE_ID} stream, call one of the <pre>stream</pre> methods
* To create a {@link StreamType#NATIVE NATIVE} stream, call one of the <pre>stream</pre> methods
* on the builder.
*/
public static class Builder {
@@ -156,27 +153,6 @@ public class Stream {
throw new IllegalArgumentException("Invalid stream source: " + streamSource);
}
/**
* Creates a {@link StreamType#TEXTURE_ID TEXTURE_ID} stream. A copy stream will sample data from the supplied
* external texture and copy it into an internal private texture.
*
* <p>Currently only OpenGL external texture ids are supported.</p>
*
* @param externalTextureId An opaque texture id (typically a GLuint created with
* <code>glGenTextures()</code>) in a context shared with
* filament -- in that case this texture's target must be
* <code>GL_TEXTURE_EXTERNAL_OES.</code>
* @return This Builder, for chaining calls.
* @see Texture#setExternalStream
* @deprecated this method existed only for ARCore which doesn't need this anymore, use {@link Texture.Builder#importTexture(long)} instead.
*/
@Deprecated
@NonNull
public Builder stream(long externalTextureId) {
nBuilderStream(mNativeBuilder, externalTextureId);
return this;
}
/**
* @param width initial width of the incoming stream. Whether this value is used is
* stream dependent. On Android, it must be set when using
@@ -276,92 +252,6 @@ public class Stream {
nSetDimensions(getNativeObject(), width, height);
}
/**
* Reads back the content of the last frame of a <code>Stream</code> since the last call to
* {@link Renderer#beginFrame}.
*
* <p>The Stream must be a copy stream, which can be checked with {@link #getStreamType()}.
* This function is a no-op otherwise.</p>
*
* <pre>
*
* Stream buffer User buffer (PixelBufferDescriptor)
* +--------------------+
* | | .stride .alignment
* | | ----------------------->-->
* | | O----------------------+--+ low addresses
* | | | | | |
* | w | | | .top | |
* | <---------> | | V | |
* | +---------+ | | +---------+ | |
* | | ^ | | ======> | | | | |
* | x | h| | | |.left| | | |
* +------>| v | | +---->| | | |
* | +.........+ | | +.........+ | |
* | ^ | | | |
* | y | | +----------------------+--+ high addresses
* O------------+-------+
*
* </pre>
*
* <p>Typically readPixels() will be called after {@link Renderer#beginFrame}.</p>
*
* <p>After calling this method, the callback associated with <code>buffer</code>
* will be invoked on the main thread, indicating that the read-back has completed.
* Typically, this will happen after multiple calls to {@link Renderer#beginFrame},
* {@link Renderer#render}, {@link Renderer#endFrame}.</p>
*
* <p><code>readPixels</code> is intended for debugging and testing.
* It will impact performance significantly.</p>
*
* @param xoffset left offset of the sub-region to read back
* @param yoffset bottom offset of the sub-region to read back
* @param width width of the sub-region to read back
* @param height height of the sub-region to read back
* @param buffer client-side buffer where the read-back will be written
*
* <p>
* The following format are always supported:
* <li>{@link Texture.Format#RGBA}</li>
* <li>{@link Texture.Format#RGBA_INTEGER}</li>
* </p>
*
* <p>
* The following types are always supported:
* <li>{@link Texture.Type#UBYTE}</li>
* <li>{@link Texture.Type#UINT}</li>
* <li>{@link Texture.Type#INT}</li>
* <li>{@link Texture.Type#FLOAT}</li>
* </p>
*
* <p>Other combination of format/type may be supported. If a combination is
* not supported, this operation may fail silently. Use a DEBUG build
* to get some logs about the failure.</p>
*
* @exception BufferOverflowException if the specified parameters would result in reading
* outside of <code>buffer</code>.
*/
public void readPixels(
@IntRange(from = 0) int xoffset, @IntRange(from = 0) int yoffset,
@IntRange(from = 0) int width, @IntRange(from = 0) int height,
@NonNull Texture.PixelBufferDescriptor buffer) {
if (buffer.storage.isReadOnly()) {
throw new ReadOnlyBufferException();
}
int result = nReadPixels(getNativeObject(), mNativeEngine,
xoffset, yoffset, width, height,
buffer.storage, buffer.storage.remaining(),
buffer.left, buffer.top, buffer.type.ordinal(), buffer.alignment,
buffer.stride, buffer.format.ordinal(),
buffer.handler, buffer.callback);
if (result < 0) {
throw new BufferOverflowException();
}
}
/**
* Returns the presentation time of the currently displayed frame in nanosecond.
*
@@ -387,7 +277,6 @@ public class Stream {
private static native long nCreateBuilder();
private static native void nDestroyBuilder(long nativeStreamBuilder);
private static native void nBuilderStreamSource(long nativeStreamBuilder, Object streamSource);
private static native void nBuilderStream(long nativeStreamBuilder, long externalTextureId);
private static native void nBuilderWidth(long nativeStreamBuilder, int width);
private static native void nBuilderHeight(long nativeStreamBuilder, int height);
private static native long nBuilderBuild(long nativeStreamBuilder, long nativeEngine);
@@ -542,7 +542,7 @@ public class Texture {
* @param alignment Alignment in bytes.
* @return Size of the buffer in bytes.
*/
static int computeDataSize(@NonNull Format format, @NonNull Type type,
public static int computeDataSize(@NonNull Format format, @NonNull Type type,
int stride, int height, @IntRange(from = 1, to = 8) int alignment) {
if (type == Type.COMPRESSED) {
return 0;
@@ -66,14 +66,14 @@ public class VertexBuffer {
BONE_INDICES, // indices of 4 bones (uvec4)
BONE_WEIGHTS, // weights of the 4 bones (normalized float4)
UNUSED, // reserved for future use
CUSTOM0, // custom
CUSTOM1, // custom
CUSTOM2, // custom
CUSTOM3, // custom
CUSTOM4, // custom
CUSTOM5, // custom
CUSTOM6, // custom
CUSTOM7 // custom
CUSTOM0, // custom or MORPH_POSITION_0
CUSTOM1, // custom or MORPH_POSITION_1
CUSTOM2, // custom or MORPH_POSITION_2
CUSTOM3, // custom or MORPH_POSITION_3
CUSTOM4, // custom or MORPH_TANGENTS_0
CUSTOM5, // custom or MORPH_TANGENTS_1
CUSTOM6, // custom or MORPH_TANGENTS_2
CUSTOM7 // custom or MORPH_TANGENTS_3
}
public enum AttributeType {
@@ -79,6 +79,7 @@ public class View {
private VignetteOptions mVignetteOptions;
private ColorGrading mColorGrading;
private TemporalAntiAliasingOptions mTemporalAntiAliasingOptions;
private ScreenSpaceReflectionsOptions mScreenSpaceReflectionsOptions;
private MultiSampleAntiAliasingOptions mMultiSampleAntiAliasingOptions;
private VsmShadowOptions mVsmShadowOptions;
private SoftShadowOptions mSoftShadowOptions;
@@ -335,6 +336,28 @@ public class View {
public boolean enabled = false;
};
/**
* Options for Screen-space Reflections.
* @see View#setScreenSpaceReflectionOptions
*/
public static class ScreenSpaceReflectionsOptions {
/** ray thickness, in world units */
public float thickness = 0.1f;
/** bias, in world units, to prevent self-intersections */
public float bias = 0.01f;
/** maximum distance, in world units, to raycast */
public float maxDistance = 3.0f;
/** stride, in texels, for samples along the ray. */
public float stride = 2.0f;
/** enables or disables screen-space reflections */
public boolean enabled = false;
};
/**
* Options for controlling the Bloom effect
*
@@ -1185,6 +1208,17 @@ public class View {
options.feedback, options.filterWidth, options.enabled);
}
/**
* Enables or disable screen-space reflections. Disabled by default.
*
* @param options screen-space reflections options
*/
public void setScreenSpaceReflectionsOptions(@NonNull ScreenSpaceReflectionsOptions options) {
mScreenSpaceReflectionsOptions = options;
nSetScreenSpaceReflectionsOptions(getNativeObject(), options.thickness, options.bias,
options.maxDistance, options.stride, options.enabled);
}
/**
* Returns temporal anti-aliasing options.
*
@@ -1198,6 +1232,19 @@ public class View {
return mTemporalAntiAliasingOptions;
}
/**
* Returns screen-space reflections options.
*
* @return screen-space reflections options
*/
@NonNull
public ScreenSpaceReflectionsOptions getScreenSpaceReflectionsOptions() {
if (mScreenSpaceReflectionsOptions == null) {
mScreenSpaceReflectionsOptions = new ScreenSpaceReflectionsOptions();
}
return mScreenSpaceReflectionsOptions;
}
/**
* Enables or disables tone-mapping in the post-processing stage. Enabled by default.
*
@@ -1782,6 +1829,7 @@ public class View {
boolean nativeResolution, int foregroundRingCount, int backgroundRingCount, int fastGatherRingCount, int maxForegroundCOC, int maxBackgroundCOC);
private static native void nSetVignetteOptions(long nativeView, float midPoint, float roundness, float feather, float r, float g, float b, float a, boolean enabled);
private static native void nSetTemporalAntiAliasingOptions(long nativeView, float feedback, float filterWidth, boolean enabled);
private static native void nSetScreenSpaceReflectionsOptions(long nativeView, float thickness, float bias, float maxDistance, float stride, boolean enabled);
private static native void nSetMultiSampleAntiAliasingOptions(long nativeView, boolean enabled, int sampleCount, boolean customResolve);
private static native boolean nIsShadowingEnabled(long nativeView);
private static native void nSetScreenSpaceRefractionEnabled(long nativeView, boolean enabled);
@@ -14,6 +14,10 @@ add_library(image STATIC IMPORTED)
set_target_properties(image PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libimage.a)
add_library(ktxreader STATIC IMPORTED)
set_target_properties(ktxreader PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libktxreader.a)
add_library(viewer STATIC IMPORTED)
set_target_properties(viewer PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libviewer.a)
@@ -64,5 +68,6 @@ target_link_libraries(filament-utils-jni
camutils
iblprefilter
image
ktxreader
viewer
)
+8 -29
View File
@@ -1,30 +1,16 @@
apply plugin: 'kotlin-android'
android {
flavorDimensions "functionality"
productFlavors {
full {
dimension "functionality"
}
lite {
dimension "functionality"
externalNativeBuild {
cmake {
// hack: this is needed because filament-utils-android/CMakeLists.txt builds
// gltfio from source, which needs this defined
arguments.add("-DGLTFIO_LITE=ON")
}
}
}
}
sourceSets {
main {
kotlin.srcDirs += "src/main/java"
}
}
defaultConfig {
missingDimensionStrategy 'functionality', 'full'
}
// No need to package up the following shared libs, which arise as a side effect of our
// externalNativeBuild dependencies. When clients pick and choose from project-level gradle
// dependencies, these shared libs already get pulled in, so we need to avoid the error:
@@ -55,9 +41,7 @@ dependencies {
implementation deps.coroutines.android
api project(':filament-android')
fullApi module("com.google.android.filament:gltfio-android:${VERSION_NAME}")
liteApi module("com.google.android.filament:gltfio-android-lite:${VERSION_NAME}")
api module("com.google.android.filament:gltfio-android:${VERSION_NAME}")
}
apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
@@ -65,14 +49,9 @@ apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
afterEvaluate {
publishing {
publications {
fullRelease(MavenPublication) {
artifactId = POM_ARTIFACT_ID_FULL
from components.fullRelease
}
liteRelease(MavenPublication) {
artifactId = POM_ARTIFACT_ID_LITE
from components.liteRelease
release(MavenPublication) {
artifactId = POM_ARTIFACT_ID
from components.release
}
}
}
@@ -1,4 +1,3 @@
POM_NAME=Filament Android Utilities
POM_ARTIFACT_ID_FULL=filament-utils-android
POM_ARTIFACT_ID_LITE=filament-utils-android-lite
POM_ARTIFACT_ID=filament-utils-android
POM_PACKAGING=aar
@@ -20,13 +20,14 @@
#include <filament/IndirectLight.h>
#include <filament/Skybox.h>
#include <image/KtxUtility.h>
#include <ktxreader/Ktx1Reader.h>
#include "common/NioUtils.h"
using namespace filament;
using namespace filament::math;
using namespace image;
using namespace ktxreader;
jlong nCreateHDRTexture(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jint internalFormat);
@@ -35,9 +36,9 @@ static jlong nCreateKTXTexture(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, javaBuffer, remaining);
KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer.getData(), buffer.getSize());
return (jlong) ktx::createTexture(engine, *bundle, srgb, [](void* userdata) {
KtxBundle* bundle = (KtxBundle*) userdata;
Ktx1Bundle* bundle = new Ktx1Bundle((const uint8_t*) buffer.getData(), buffer.getSize());
return (jlong) Ktx1Reader::createTexture(engine, *bundle, srgb, [](void* userdata) {
Ktx1Bundle* bundle = (Ktx1Bundle*) userdata;
delete bundle;
}, bundle);
}
@@ -46,9 +47,9 @@ static jlong nCreateIndirectLight(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, javaBuffer, remaining);
KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer.getData(), buffer.getSize());
Texture* cubemap = ktx::createTexture(engine, *bundle, srgb, [](void* userdata) {
KtxBundle* bundle = (KtxBundle*) userdata;
Ktx1Bundle* bundle = new Ktx1Bundle((const uint8_t*) buffer.getData(), buffer.getSize());
Texture* cubemap = Ktx1Reader::createTexture(engine, *bundle, srgb, [](void* userdata) {
Ktx1Bundle* bundle = (Ktx1Bundle*) userdata;
delete bundle;
}, bundle);
@@ -68,9 +69,9 @@ static jlong nCreateSkybox(JNIEnv* env, jclass,
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, javaBuffer, remaining);
KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer.getData(), buffer.getSize());
Texture* cubemap = ktx::createTexture(engine, *bundle, srgb, [](void* userdata) {
KtxBundle* bundle = (KtxBundle*) userdata;
Ktx1Bundle* bundle = new Ktx1Bundle((const uint8_t*) buffer.getData(), buffer.getSize());
Texture* cubemap = Ktx1Reader::createTexture(engine, *bundle, srgb, [](void* userdata) {
Ktx1Bundle* bundle = (Ktx1Bundle*) userdata;
delete bundle;
}, bundle);
return (jlong) Skybox::Builder().environment(cubemap).showSun(true).build(*engine);
@@ -79,7 +80,7 @@ static jlong nCreateSkybox(JNIEnv* env, jclass,
static jboolean nGetSphericalHarmonics(JNIEnv* env, jclass, jobject javaBuffer, jint remaining,
jfloatArray outSphericalHarmonics_) {
AutoBuffer buffer(env, javaBuffer, remaining);
KtxBundle bundle((const uint8_t*) buffer.getData(), buffer.getSize());
Ktx1Bundle bundle((const uint8_t*) buffer.getData(), buffer.getSize());
jfloat* outSphericalHarmonics = env->GetFloatArrayElements(outSphericalHarmonics_, nullptr);
const auto success = bundle.getSphericalHarmonics(
@@ -98,8 +99,8 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
int rc;
// KTXLoader
jclass ktxloaderClass = env->FindClass("com/google/android/filament/utils/KTXLoader");
// KTX1Loader
jclass ktxloaderClass = env->FindClass("com/google/android/filament/utils/KTX1Loader");
if (ktxloaderClass == nullptr) return JNI_ERR;
static const JNINativeMethod ktxMethods[] = {
{(char*)"nCreateKTXTexture", (char*)"(JLjava/nio/Buffer;IZ)J", reinterpret_cast<void*>(nCreateKTXTexture)},
@@ -40,7 +40,7 @@ import com.google.android.filament.Renderer;
*
* When executing a test, clients should call tick() after each frame is rendered, which provides an
* opportunity to push settings to Filament, increment the current test index (if enough time has
* elapsed), and request an asychronous screenshot.
* elapsed), and request an asynchronous screenshot.
*
* The time to sleep between tests is configurable and can be set to zero. Automation also waits a
* specified minimum number of frames between tests.
@@ -24,12 +24,12 @@ import com.google.android.filament.Texture
import java.nio.Buffer
/**
* Utilities for consuming KTX files and producing Filament textures, IBLs, and sky boxes.
* Utilities for consuming KTX1 files and producing Filament textures, IBLs, and sky boxes.
*
* KTX is a simple container format that makes it easy to bundle miplevels and cubemap faces
* into a single file.
*/
object KTXLoader {
object KTX1Loader {
class Options {
var srgb = false
}
@@ -14,6 +14,8 @@
* limitations under the License.
*/
@file:Suppress("unused")
package com.google.android.filament.utils
import kotlin.math.*
@@ -22,6 +24,10 @@ enum class MatrixColumn {
X, Y, Z, W
}
enum class RotationsOrder {
XYZ, XZY, YXZ, YZX, ZXY, ZYX
}
data class Mat2(
var x: Float2 = Float2(x = 1.0f),
var y: Float2 = Float2(y = 1.0f)) {
@@ -39,14 +45,14 @@ data class Mat2(
fun identity() = Mat2()
}
operator fun get(column: Int) = when(column) {
operator fun get(column: Int) = when (column) {
0 -> x
1 -> y
else -> throw IllegalArgumentException("column must be in 0..1")
}
operator fun get(column: Int, row: Int) = get(column)[row]
operator fun get(column: MatrixColumn) = when(column) {
operator fun get(column: MatrixColumn) = when (column) {
MatrixColumn.X -> x
MatrixColumn.Y -> y
else -> throw IllegalArgumentException("column must be X or Y")
@@ -64,16 +70,8 @@ data class Mat2(
}
operator fun unaryMinus() = Mat2(-x, -y)
operator fun inc(): Mat2 {
x++
y++
return this
}
operator fun dec(): Mat2 {
x--
y--
return this
}
operator fun inc() = Mat2(x++, y++)
operator fun dec() = Mat2(x--, y--)
operator fun plus(v: Float) = Mat2(x + v, y + v)
operator fun minus(v: Float) = Mat2(x - v, y - v)
@@ -130,7 +128,7 @@ data class Mat3(
fun identity() = Mat3()
}
operator fun get(column: Int) = when(column) {
operator fun get(column: Int) = when (column) {
0 -> x
1 -> y
2 -> z
@@ -138,7 +136,7 @@ data class Mat3(
}
operator fun get(column: Int, row: Int) = get(column)[row]
operator fun get(column: MatrixColumn) = when(column) {
operator fun get(column: MatrixColumn) = when (column) {
MatrixColumn.X -> x
MatrixColumn.Y -> y
MatrixColumn.Z -> z
@@ -157,18 +155,8 @@ data class Mat3(
}
operator fun unaryMinus() = Mat3(-x, -y, -z)
operator fun inc(): Mat3 {
x++
y++
z++
return this
}
operator fun dec(): Mat3 {
x--
y--
z--
return this
}
operator fun inc() = Mat3(x++, y++, z++)
operator fun dec() = Mat3(x--, y--, z--)
operator fun plus(v: Float) = Mat3(x + v, y + v, z + v)
operator fun minus(v: Float) = Mat3(x - v, y - v, z - v)
@@ -279,7 +267,7 @@ data class Mat4(
inline val upperLeft: Mat3
get() = Mat3(x.xyz, y.xyz, z.xyz)
operator fun get(column: Int) = when(column) {
operator fun get(column: Int) = when (column) {
0 -> x
1 -> y
2 -> z
@@ -288,7 +276,7 @@ data class Mat4(
}
operator fun get(column: Int, row: Int) = get(column)[row]
operator fun get(column: MatrixColumn) = when(column) {
operator fun get(column: MatrixColumn) = when (column) {
MatrixColumn.X -> x
MatrixColumn.Y -> y
MatrixColumn.Z -> z
@@ -307,20 +295,8 @@ data class Mat4(
}
operator fun unaryMinus() = Mat4(-x, -y, -z, -w)
operator fun inc(): Mat4 {
x++
y++
z++
w++
return this
}
operator fun dec(): Mat4 {
x--
y--
z--
w--
return this
}
operator fun inc() = Mat4(x++, y++, z++, w++)
operator fun dec() = Mat4(x--, y--, z--, w--)
operator fun plus(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)
@@ -361,6 +337,8 @@ data class Mat4(
x.w * v.x + y.w * v.y + z.w * v.z+ w.w * v.w
)
fun toQuaternion() = quaternion(this)
fun toFloatArray() = floatArrayOf(
x.x, y.x, z.x, w.x,
x.y, y.y, z.y, w.y,
@@ -408,7 +386,7 @@ fun inverse(m: Mat3): Mat3 {
val det = a * A + b * B + c * C
return Mat3.of(
A / det, B / det, C / det,
A / det, B / det, C / det,
(c * h - b * i) / det, (a * i - c * g) / det, (b * g - a * h) / det,
(b * f - c * e) / det, (c * d - a * f) / det, (a * e - b * d) / det
)
@@ -496,18 +474,90 @@ fun translation(t: Float3) = Mat4(w = Float4(t, 1.0f))
fun translation(m: Mat4) = translation(m.translation)
fun rotation(m: Mat4) = Mat4(normalize(m.right), normalize(m.up), normalize(m.forward))
fun rotation(d: Float3): Mat4 {
val r = transform(d, ::radians)
val c = transform(r) { x -> cos(x) }
val s = transform(r) { x -> sin(x) }
return Mat4.of(
c.y * c.z, -c.x * s.z + s.x * s.y * c.z, s.x * s.z + c.x * s.y * c.z, 0.0f,
c.y * s.z, c.x * c.z + s.x * s.y * s.z, -s.x * c.z + c.x * s.y * s.z, 0.0f,
-s.y , s.x * c.y , c.x * c.y , 0.0f,
0.0f , 0.0f , 0.0f , 1.0f
)
/**
* Construct a rotation matrix from Euler angles using YPR around a specified order
*
* Uses intrinsic Tait-Bryan angles. This means that rotations are performed with respect to 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
* 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.
*
* @return The rotation matrix
*/
fun rotation(d: Float3, order: RotationsOrder = RotationsOrder.ZYX): Mat4 {
val r = transform(d, ::radians)
return when(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)
}
}
/**
* Construct a rotation matrix from Euler yaw, pitch, roll around a specified order.
*
* @param roll about 1st rotation axis in radians. Z in case of ZYX order
* @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 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.
*
* @return The rotation matrix
*/
fun rotation(yaw: Float = 0.0f, pitch: Float = 0.0f, roll: Float = 0.0f, order: RotationsOrder = RotationsOrder.ZYX): Mat4 {
val c1 = cos(yaw)
val s1 = sin(yaw)
val c2 = cos(pitch)
val s2 = sin(pitch)
val c3 = cos(roll)
val s3 = sin(roll)
return when (order) {
RotationsOrder.XZY -> Mat4.of(
c2 * c3, -s2, c2 * s3, 0.0f,
s1 * s3 + c1 * c3 * s2, c1 * c2, c1 * s2 * s3 - c3 * s1, 0.0f,
c3 * s1 * s2 - c1 * s3, c2 * s1, c1 * c3 + s1 * s2 * s3, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f)
RotationsOrder.XYZ -> Mat4.of(
c2 * c3, -c2 * s3, s2, 0.0f,
c1 * s3 + c3 * s1 * s2, c1 * c3 - s1 * s2 * s3, -c2 * s1, 0.0f,
s1 * s3 - c1 * c3 * s2, c3 * s1 + c1 * s2 * s3, c1 * c2, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f)
RotationsOrder.YXZ -> Mat4.of(
c1 * c3 + s1 * s2 * s3, c3 * s1 * s2 - c1 * s3, c2 * s1, 0.0f,
c2 * s3, c2 * c3, -s2, 0.0f,
c1 * s2 * s3 - c3 * s1, c1 * c3 * s2 + s1 * s3, c1 * c2, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f)
RotationsOrder.YZX -> Mat4.of(
c1 * c2, s1 * s3 - c1 * c3 * s2, c3 * s1 + c1 * s2 * s3, 0.0f,
s2, c2 * c3, -c2 * s3, 0.0f,
-c2 * s1, c1 * s3 + c3 * s1 * s2, c1 * c3 - s1 * s2 * s3, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f)
RotationsOrder.ZYX -> Mat4.of(
c1 * c2, c1 * s2 * s3 - c3 * s1, s1 * s3 + c1 * c3 * s2, 0.0f,
c2 * s1, c1 * c3 + s1 * s2 * s3, c3 * s1 * s2 - c1 * s3, 0.0f,
-s2, c2 * s3, c2 * c3, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f)
RotationsOrder.ZXY -> Mat4.of(
c1 * c3 - s1 * s2 * s3, -c2 * s1, c1 * s3 + c3 * s1 * s2, 0.0f,
c3 * s1 + c1 * s2 * s3, c1 * c2, s1 * s3 - c1 * c3 * s2, 0.0f,
-c2 * s3, s2, c2 * c3, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f)
}
}
fun rotation(axis: Float3, angle: Float): Mat4 {
val x = axis.x
val y = axis.y
@@ -519,10 +569,85 @@ fun rotation(axis: Float3, angle: Float): Mat4 {
val d = 1.0f - c
return Mat4.of(
x * x * d + c , x * y * d - z * s, x * z * d + y * s, 0.0f,
y * x * d + z * s, y * y * d + c , y * z * d - x * s, 0.0f,
z * x * d - y * s, z * y * d + x * s, z * z * d + c , 0.0f,
0.0f , 0.0f , 0.0f , 1.0f
x * x * d + c, x * y * d - z * s, x * z * d + y * s, 0.0f,
y * x * d + z * s, y * y * d + c, y * z * d - x * s, 0.0f,
z * x * d - y * s, z * y * d + x * s, z * z * d + c, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
)
}
/**
* Construct a Quaternion Rotation Matrix following the Hamilton convention
*
* Assume the destination and local coordinate spaces are initially aligned, and the local
* coordinate space is then rotated counter-clockwise about a unit-length axis, k, by an angle,
* theta.
*/
fun rotation(quaternion: Quaternion): Mat4 {
val n = normalize(quaternion)
return Mat4(
Float4(
1.0f - 2.0f * (n.y * n.y + n.z * n.z),
2.0f * (n.x * n.y + n.z * n.w),
2.0f * (n.x * n.z - n.y * n.w),
),
Float4(
2.0f * (n.x * n.y - n.z * n.w),
1.0f - 2.0f * (n.x * n.x + n.z * n.z),
2.0f * (n.y * n.z + n.x * n.w),
),
Float4(
2.0f * (n.x * n.z + n.y * n.w),
2.0f * (n.y * n.z - n.x * n.w),
1.0f - 2.0f * (n.x * n.x + n.y * n.y),
)
)
}
/**
* Extract Quaternion rotation from a Matrix
*/
fun quaternion(m: Mat4): Quaternion {
val trace = m.x.x + m.y.y + m.z.z
return normalize(
when {
trace > 0.0f -> {
val s = 2.0f * sqrt(trace + 1.0f)
Quaternion(
(m.y.z - m.z.y) / s,
(m.z.x - m.x.z) / s,
(m.x.y - m.y.x) / s,
0.25f * s
)
}
m.x.x > m.y.y && m.x.x > m.z.z -> {
val s = 2.0f * sqrt(1.0f + m.x.x - m.y.y - m.z.z)
Quaternion(
0.25f * s,
(m.y.x + m.x.y) / s,
(m.z.x + m.x.z) / s,
(m.y.z - m.z.y) / s
)
}
m.y.y > m.z.z -> {
val s = 2.0f * sqrt(1.0f + m.y.y - m.x.x - m.z.z)
Quaternion(
(m.y.x + m.x.y) / s,
0.25f * s,
(m.z.y + m.y.z) / s,
(m.z.x - m.x.z) / s
)
}
else -> {
val s = 2.0f * sqrt(1.0f + m.z.z - m.x.x - m.y.y)
Quaternion(
(m.z.x + m.x.z) / s,
(m.z.y + m.y.z) / s,
0.25f * s,
(m.x.y - m.y.x) / s
)
}
}
)
}
@@ -536,7 +661,7 @@ fun lookTowards(eye: Float3, forward: Float3, up: Float3 = Float3(z = 1.0f)): Ma
val f = normalize(forward)
val r = normalize(f x up)
val u = normalize(r x f)
return Mat4(Float4(r), Float4(u), Float4(f), Float4(eye, 1.0f))
return Mat4(Float4(r), Float4(u), Float4(-f), Float4(eye, 1.0f))
}
fun perspective(fov: Float, ratio: Float, near: Float, far: Float): Mat4 {
@@ -98,6 +98,7 @@ class ModelViewer(
private var swapChain: SwapChain? = null
private var assetLoader: AssetLoader
private var materialProvider: MaterialProvider
private var resourceLoader: ResourceLoader
private val readyRenderables = IntArray(128) // add up to 128 entities at a time
@@ -113,7 +114,8 @@ class ModelViewer(
view.scene = scene
view.camera = camera
assetLoader = AssetLoader(engine, UbershaderLoader(engine), EntityManager.get())
materialProvider = UbershaderLoader(engine)
assetLoader = AssetLoader(engine, materialProvider, EntityManager.get())
resourceLoader = ResourceLoader(engine, normalizeSkinningWeights, recomputeBoundingBoxes, ignoreBindTransform)
// Always add a direct light source since it is required for shadowing.
@@ -316,6 +318,8 @@ class ModelViewer(
destroyModel()
assetLoader.destroy()
materialProvider.destroyMaterials()
materialProvider.destroy()
resourceLoader.destroy()
engine.destroyEntity(light)
@@ -0,0 +1,342 @@
/*
* Copyright (C) 2022 Romain Guy
*
* 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.
*/
@file:Suppress("NOTHING_TO_INLINE", "unused")
package com.google.android.filament.utils
import kotlin.math.*
enum class QuaternionComponent {
X, Y, Z, W
}
/**
* Construct Quaternion and set each value.
* The Quaternion will be normalized during construction
* Default: Identity
*/
data class Quaternion(
var x: Float = 0.0f,
var y: Float = 0.0f,
var z: Float = 0.0f,
var w: Float = 0.0f) {
constructor(v: Float3, w: Float = 0.0f) : this(v.x, v.y, v.z, 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)
companion object {
/**
* Construct a Quaternion from an axis and angle in degrees
*
* @param axis Rotation direction
* @param angle Angle size in degrees
*/
fun fromAxisAngle(axis: Float3, angle: Float): Quaternion {
val r = radians(angle)
return Quaternion(sin(r * 0.5f) * normalize(axis), cos(r * 0.5f))
}
/**
* Construct a Quaternion from Euler angles using YPR around ZYX respectively
*
* The Euler angles are applied in ZYX order.
* i.e: a vector is first rotated about X (roll) then Y (pitch) and then Z (yaw).
*
* @param d Per axis Euler angles in degrees
*/
fun fromEuler(d: Float3): Quaternion {
val r = transform(d, ::radians)
return fromEulerZYX(r.z, r.y, r.x)
}
/**
* Construct a Quaternion from Euler angles using YPR around ZYX respectively
*
* The Euler angles are applied in ZYX order.
* i.e: a vector is first rotated about X (roll) then Y (pitch) and then Z (yaw).
*
* @param roll about X axis in radians
* @param pitch about Y axis in radians
* @param yaw about Z axis in radians
*/
fun fromEulerZYX(yaw: Float = 0.0f, pitch: Float = 0.0f, roll: Float = 0.0f): Quaternion {
val cy = cos(yaw * 0.5f)
val sy = sin(yaw * 0.5f)
val cp = cos(pitch * 0.5f)
val sp = sin(pitch * 0.5f)
val cr = cos(roll * 0.5f)
val sr = sin(roll * 0.5f)
return Quaternion(
sr * cp * cy - cr * sp * sy,
cr * sp * cy + sr * cp * sy,
cr * cp * sy - sr * sp * cy,
cr * cp * cy + sr * sp * sy
)
}
}
inline var xyz: Float3
get() = Float3(x, y, z)
set(value) {
x = value.x
y = value.y
z = value.z
}
inline var imaginary: Float3
get() = xyz
set(value) {
x = value.x
y = value.y
z = value.z
}
inline var real: Float
get() = w
set(value) {
w = value
}
inline var xyzw: Float4
get() = Float4(x, y, z, w)
set(value) {
x = value.x
y = value.y
z = value.z
w = value.w
}
operator fun get(index: QuaternionComponent) = when (index) {
QuaternionComponent.X -> x
QuaternionComponent.Y -> y
QuaternionComponent.Z -> z
QuaternionComponent.W -> w
}
operator fun get(
index1: QuaternionComponent,
index2: QuaternionComponent,
index3: QuaternionComponent): Float3 {
return Float3(get(index1), get(index2), get(index3))
}
operator fun get(
index1: QuaternionComponent,
index2: QuaternionComponent,
index3: QuaternionComponent,
index4: QuaternionComponent): Quaternion {
return Quaternion(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, index3: Int): Float3 {
return Float3(get(index1), get(index2), get(index3))
}
operator fun get(index1: Int, index2: Int, index3: Int, index4: Int): Quaternion {
return Quaternion(get(index1), get(index2), get(index3), get(index4))
}
inline operator fun invoke(index: Int) = get(index - 1)
operator fun set(index: Int, v: Float) = 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: Float) {
set(index1, v)
set(index2, v)
}
operator fun set(index1: Int, index2: Int, index3: Int, v: Float) {
set(index1, v)
set(index2, v)
set(index3, v)
}
operator fun set(index1: Int, index2: Int, index3: Int, index4: Int, v: Float) {
set(index1, v)
set(index2, v)
set(index3, v)
set(index4, v)
}
operator fun set(index: QuaternionComponent, v: Float) = when (index) {
QuaternionComponent.X -> x = v
QuaternionComponent.Y -> y = v
QuaternionComponent.Z -> z = v
QuaternionComponent.W -> w = v
}
operator fun set(index1: QuaternionComponent, index2: QuaternionComponent, v: Float) {
set(index1, v)
set(index2, v)
}
operator fun set(
index1: QuaternionComponent, index2: QuaternionComponent, index3: QuaternionComponent, v: Float) {
set(index1, v)
set(index2, v)
set(index3, v)
}
operator fun set(
index1: QuaternionComponent, index2: QuaternionComponent,
index3: QuaternionComponent, index4: QuaternionComponent, v: Float) {
set(index1, v)
set(index2, v)
set(index3, v)
set(index4, v)
}
operator fun unaryMinus() = Quaternion(-x, -y, -z, -w)
inline operator fun plus(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 div(v: Float) = Quaternion(x / v, y / v, z / v, w / v)
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 minus(q: Quaternion) = Quaternion(x - q.x, y - q.y, z - q.z, w - q.w)
inline operator fun times(q: Quaternion) = Quaternion(
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.z + x * q.y - y * q.x + z * q.w,
w * q.w - x * q.x - y * q.y - z * q.z)
inline fun transform(block: (Float) -> Float): Quaternion {
x = block(x)
y = block(y)
z = block(z)
w = block(w)
return this
}
fun toEulerAngles() = eulerAngles(this)
fun toMatrix() = rotation(this)
fun toFloatArray() = floatArrayOf(x, y, z, w)
}
inline operator fun Float.plus(q: Quaternion) = Quaternion(this + q.x, this + q.y, this + q.z, this + q.w)
inline operator fun Float.minus(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 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 length2(q: Quaternion) = q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w
inline fun dot(a: Quaternion, b: Quaternion) = a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w
/**
* Rescale the Quaternion to the unit length
*/
fun normalize(q: Quaternion): Quaternion {
val l = 1.0f / length(q)
return Quaternion(q.x * l, q.y * l, q.z * l, q.w * l)
}
fun conjugate(q: Quaternion): Quaternion = Quaternion(-q.x, -q.y, -q.z, q.w)
fun inverse(q: Quaternion): Quaternion {
val d = 1.0f / dot(q, q)
return Quaternion(-q.x * d, -q.y * d, -q.z * d, q.w * d)
}
fun cross(a: Quaternion, b: Quaternion): Quaternion {
val m = a * b
return Quaternion(m.x, m.y, m.z, 0.0f)
}
/**
* Spherical linear interpolation between two given orientations
*
* If t is 0 this returns a.
* As t approaches 1 slerp may approach either b or -b (whichever is closest to a)
* If t is above 1 or below 0 the result will be extrapolated.
* @param a The beginning value
* @param b The ending value
* @param t The ratio between the two floats
* @param valueEps Prevent blowing up when slerping between two quaternions that are very near each
* other. Linear interpolation (lerp) is returned in this case.
*
* @return Interpolated value between the two floats
*/
fun slerp(a: Quaternion, b: Quaternion, t: Float, valueEps: Float = 0.0000000001f): Quaternion {
// could also be computed as: pow(q * inverse(p), t) * p;
val d = dot(a, b)
val absd = abs(d)
// Prevent blowing up when slerping between two quaternions that are very near each other.
if ((1.0f - absd) < valueEps) {
return normalize(lerp(if (d < 0.0f) -a else a, b, 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 {
return ((1 - t) * a) + (t * b)
}
fun nlerp(a: Quaternion, b: Quaternion, t: Float): Quaternion {
return normalize(lerp(a, b, t))
}
/**
* Convert a Quaternion to Euler angles using YPR around ZYX respectively
*
* The Euler angles are applied in ZYX order
*/
fun eulerAngles(q: Quaternion): Float3 {
val nq = normalize(q)
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)))
}
@@ -18,6 +18,8 @@
package com.google.android.filament.utils
import kotlin.math.pow
const val FPI = 3.1415926536f
const val HALF_PI = FPI * 0.5f
const val TWO_PI = FPI * 2.0f
@@ -40,4 +42,4 @@ inline fun fract(v: Float) = v % 1
inline fun sqr(v: Float) = v * v
inline fun pow(x: Float, y: Float) = StrictMath.pow(x.toDouble(), y.toDouble()).toFloat()
inline fun pow(x: Float, y: Float) = (x.toDouble().pow(y.toDouble())).toFloat()
@@ -14,7 +14,7 @@
* limitations under the License.
*/
@file:Suppress("NOTHING_TO_INLINE")
@file:Suppress("NOTHING_TO_INLINE", "unused")
package com.google.android.filament.utils
@@ -117,17 +117,8 @@ data class Float2(var x: Float = 0.0f, var y: Float = 0.0f) {
}
operator fun unaryMinus() = Float2(-x, -y)
operator fun inc(): Float2 {
x += 1.0f
y += 1.0f
return this
}
operator fun dec(): Float2 {
x -= 1.0f
y -= 1.0f
return this
}
operator fun inc() = Float2(x++, y++)
operator fun dec() = Float2(x--, y--)
inline operator fun plus(v: Float) = Float2(x + v, y + v)
inline operator fun minus(v: Float) = Float2(x - v, y - v)
@@ -144,6 +135,8 @@ data class Float2(var x: Float = 0.0f, var y: Float = 0.0f) {
y = block(y)
return this
}
fun toFloatArray() = floatArrayOf(x, y)
}
data class Float3(var x: Float = 0.0f, var y: Float = 0.0f, var z: Float = 0.0f) {
@@ -284,29 +277,15 @@ data class Float3(var x: Float = 0.0f, var y: Float = 0.0f, var z: Float = 0.0f)
}
operator fun set(
index1: VectorComponent,
index2: VectorComponent,
index3: VectorComponent,
v: Float) {
index1: VectorComponent, index2: VectorComponent, index3: VectorComponent, v: Float) {
set(index1, v)
set(index2, v)
set(index3, v)
}
operator fun unaryMinus() = Float3(-x, -y, -z)
operator fun inc(): Float3 {
x += 1.0f
y += 1.0f
z += 1.0f
return this
}
operator fun dec(): Float3 {
x -= 1.0f
y -= 1.0f
z -= 1.0f
return this
}
operator fun inc() = Float3(x++, y++, z++)
operator fun dec() = Float3(x--, y--, z--)
inline operator fun plus(v: Float) = Float3(x + v, y + v, z + v)
inline operator fun minus(v: Float) = Float3(x - v, y - v, z - v)
@@ -329,6 +308,8 @@ data class Float3(var x: Float = 0.0f, var y: Float = 0.0f, var z: Float = 0.0f)
z = block(z)
return this
}
fun toFloatArray() = floatArrayOf(x, y, z)
}
data class Float4(
@@ -529,14 +510,15 @@ data class Float4(
set(index2, v)
}
operator fun set(index1: VectorComponent, index2: VectorComponent, index3: VectorComponent,
v: Float) {
operator fun set(
index1: VectorComponent, index2: VectorComponent, index3: VectorComponent, v: Float) {
set(index1, v)
set(index2, v)
set(index3, v)
}
operator fun set(index1: VectorComponent, index2: VectorComponent,
operator fun set(
index1: VectorComponent, index2: VectorComponent,
index3: VectorComponent, index4: VectorComponent, v: Float) {
set(index1, v)
set(index2, v)
@@ -545,21 +527,8 @@ data class Float4(
}
operator fun unaryMinus() = Float4(-x, -y, -z, -w)
operator fun inc(): Float4 {
x += 1.0f
y += 1.0f
z += 1.0f
w += 1.0f
return this
}
operator fun dec(): Float4 {
x -= 1.0f
y -= 1.0f
z -= 1.0f
w -= 1.0f
return this
}
operator fun inc() = Float4(x++, y++, z++, w++)
operator fun dec() = Float4(x--, y--, z--, w--)
inline operator fun plus(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)
@@ -588,6 +557,8 @@ data class Float4(
w = block(w)
return this
}
fun toFloatArray() = floatArrayOf(x, y, z, w)
}
inline operator fun Float.plus(v: Float2) = Float2(this + v.x, this + v.y)
@@ -615,25 +586,29 @@ fun refract(i: Float2, n: Float2, eta: Float): Float2 {
inline fun clamp(v: Float2, min: Float, max: Float): Float2 {
return Float2(
clamp(v.x, min, max),
clamp(v.y, min, max))
clamp(v.y, min, max)
)
}
inline fun clamp(v: Float2, min: Float2, max: Float2): Float2 {
return Float2(
clamp(v.x, min.x, max.x),
clamp(v.y, min.y, max.y))
clamp(v.y, min.y, max.y)
)
}
inline fun mix(a: Float2, b: Float2, x: Float): Float2 {
return Float2(
mix(a.x, b.x, x),
mix(a.y, b.y, x))
mix(a.y, b.y, x)
)
}
inline fun mix(a: Float2, b: Float2, x: Float2): Float2 {
return Float2(
mix(a.x, b.x, x.x),
mix(a.y, b.y, x.y))
mix(a.y, b.y, x.y)
)
}
inline fun min(v: Float2) = min(v.x, v.y)
@@ -704,28 +679,32 @@ inline fun clamp(v: Float3, min: Float, max: Float): Float3 {
return Float3(
clamp(v.x, min, max),
clamp(v.y, min, max),
clamp(v.z, min, max))
clamp(v.z, min, max)
)
}
inline fun clamp(v: Float3, min: Float3, max: Float3): Float3 {
return Float3(
clamp(v.x, min.x, max.x),
clamp(v.y, min.y, max.y),
clamp(v.z, min.z, max.z))
clamp(v.z, min.z, max.z)
)
}
inline fun mix(a: Float3, b: Float3, x: Float): Float3 {
return Float3(
mix(a.x, b.x, x),
mix(a.y, b.y, x),
mix(a.z, b.z, x))
mix(a.z, b.z, x)
)
}
inline fun mix(a: Float3, b: Float3, x: Float3): Float3 {
return Float3(
mix(a.x, b.x, x.x),
mix(a.y, b.y, x.y),
mix(a.z, b.z, x.z))
mix(a.z, b.z, x.z)
)
}
inline fun min(v: Float3) = min(v.x, min(v.y, v.z))
@@ -784,7 +763,8 @@ inline fun clamp(v: Float4, min: Float, max: Float): Float4 {
clamp(v.x, min, max),
clamp(v.y, min, max),
clamp(v.z, min, max),
clamp(v.w, min, max))
clamp(v.w, min, max)
)
}
inline fun clamp(v: Float4, min: Float4, max: Float4): Float4 {
@@ -792,7 +772,8 @@ inline fun clamp(v: Float4, min: Float4, max: Float4): Float4 {
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))
clamp(v.w, min.z, max.w)
)
}
inline fun mix(a: Float4, b: Float4, x: Float): Float4 {
@@ -800,7 +781,8 @@ inline fun mix(a: Float4, b: Float4, x: Float): Float4 {
mix(a.x, b.x, x),
mix(a.y, b.y, x),
mix(a.z, b.z, x),
mix(a.w, b.w, x))
mix(a.w, b.w, x)
)
}
inline fun mix(a: Float4, b: Float4, x: Float4): Float4 {
@@ -1075,10 +1057,7 @@ data class Bool3(var x: Boolean = false, var y: Boolean = false, var z: Boolean
}
operator fun set(
index1: VectorComponent,
index2: VectorComponent,
index3: VectorComponent,
v: Boolean) {
index1: VectorComponent, index2: VectorComponent, index3: VectorComponent, v: Boolean) {
set(index1, v)
set(index2, v)
set(index3, v)
@@ -1282,14 +1261,15 @@ data class Bool4(
set(index2, v)
}
operator fun set(index1: VectorComponent, index2: VectorComponent, index3: VectorComponent,
v: Boolean) {
operator fun set(
index1: VectorComponent, index2: VectorComponent, index3: VectorComponent, v: Boolean) {
set(index1, v)
set(index2, v)
set(index3, v)
}
operator fun set(index1: VectorComponent, index2: VectorComponent,
operator fun set(
index1: VectorComponent, index2: VectorComponent,
index3: VectorComponent, index4: VectorComponent, v: Boolean) {
set(index1, v)
set(index2, v)
+19 -6
View File
@@ -11,6 +11,18 @@ add_library(dracodec STATIC IMPORTED)
set_target_properties(dracodec PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libdracodec.a)
add_library(ktxreader STATIC IMPORTED)
set_target_properties(ktxreader PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libktxreader.a)
add_library(stb STATIC IMPORTED)
set_target_properties(stb PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libstb.a)
add_library(basis_transcoder STATIC IMPORTED)
set_target_properties(basis_transcoder PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libbasis_transcoder.a)
add_library(utils STATIC IMPORTED)
set_target_properties(utils PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libutils.a)
@@ -32,6 +44,8 @@ set(GLTFIO_SRCS
${GLTFIO_DIR}/include/gltfio/ResourceLoader.h
${GLTFIO_DIR}/include/gltfio/FilamentAsset.h
${GLTFIO_DIR}/include/gltfio/FilamentInstance.h
${GLTFIO_DIR}/include/gltfio/TextureProvider.h
${GLTFIO_DIR}/include/gltfio/math.h
${GLTFIO_DIR}/src/Animator.cpp
${GLTFIO_DIR}/src/AssetLoader.cpp
@@ -44,18 +58,16 @@ set(GLTFIO_SRCS
${GLTFIO_DIR}/src/FFilamentInstance.h
${GLTFIO_DIR}/src/FilamentInstance.cpp
${GLTFIO_DIR}/src/GltfEnums.h
${GLTFIO_DIR}/src/Ktx2Provider.cpp
${GLTFIO_DIR}/src/MaterialProvider.cpp
${GLTFIO_DIR}/src/MorphHelper.h
${GLTFIO_DIR}/src/MorphHelper.cpp
${GLTFIO_DIR}/src/ResourceLoader.cpp
${GLTFIO_DIR}/src/StbProvider.cpp
${GLTFIO_DIR}/src/TangentsJob.h
${GLTFIO_DIR}/src/TangentsJob.cpp
${GLTFIO_DIR}/src/UbershaderLoader.cpp
${GLTFIO_DIR}/src/Wireframe.cpp
${GLTFIO_DIR}/src/Wireframe.h
${GLTFIO_DIR}/src/math.h
${GLTFIO_DIR}/src/upcast.h
${GLTFIO_DIR}/src/Image.cpp
src/main/cpp/Animator.cpp
src/main/cpp/AssetLoader.cpp
@@ -83,6 +95,7 @@ set(GLTFIO_INCLUDE_DIRS
../../third_party/hat-trie
../../third_party/stb
../../libs/utils/include
../../libs/ktxreader/include
)
add_library(gltfio-jni SHARED ${GLTFIO_SRCS})
@@ -92,9 +105,9 @@ set_target_properties(gltfio-jni PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_
if(GLTFIO_LITE)
target_compile_definitions(gltfio-jni PUBLIC GLTFIO_LITE=1)
target_link_libraries(gltfio-jni filament-jni utils log gltfio_resources_lite)
target_link_libraries(gltfio-jni filament-jni utils log stb ktxreader basis_transcoder gltfio_resources_lite)
else()
target_link_libraries(gltfio-jni filament-jni utils log gltfio_resources)
target_link_libraries(gltfio-jni filament-jni utils log stb ktxreader basis_transcoder gltfio_resources)
# Enable Draco in the non-lite variant of gltfio.
target_link_libraries(gltfio-jni dracodec)
@@ -36,6 +36,12 @@ Java_com_google_android_filament_gltfio_Animator_nUpdateBoneMatrices(JNIEnv*, jc
animator->updateBoneMatrices();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_Animator_nResetBoneMatrices(JNIEnv*, jclass, jlong nativeAnimator) {
Animator* animator = (Animator*) nativeAnimator;
animator->resetBoneMatrices();
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_gltfio_Animator_nGetAnimationCount(JNIEnv*, jclass, jlong nativeAnimator) {
Animator* animator = (Animator*) nativeAnimator;
@@ -69,7 +69,7 @@ public:
jclass providerClass = env->GetObjectClass(provider);
mCreateMaterialInstance = env->GetMethodID(providerClass, "createMaterialInstance",
"(L" JAVA_MATERIAL_KEY ";[ILjava/lang/String;)Lcom/google/android/filament/MaterialInstance;");
"(L" JAVA_MATERIAL_KEY ";[ILjava/lang/String;Ljava/lang/String;)Lcom/google/android/filament/MaterialInstance;");
assert_invariant(mCreateMaterialInstance);
mGetMaterials = env->GetMethodID(providerClass, "getMaterials",
@@ -89,7 +89,7 @@ public:
delete mPreviousMaterials;
}
MaterialInstance* createMaterialInstance(MaterialKey* config, UvMap* uvmap, const char* label) override {
MaterialInstance* createMaterialInstance(MaterialKey* config, UvMap* uvmap, const char* label, const char* extras) override {
// Create a Java object for the material key and copy the native fields into it.
jobject javaKey = mEnv->NewObject(mMaterialKeyClass, mMaterialKeyConstructor);
@@ -99,12 +99,15 @@ public:
// Convert the optional label into a Java string.
jstring stringLabel = label ? mEnv->NewStringUTF(label) : nullptr;
// Convert the optional extras into a Java string.
jstring stringExtras = extras ? mEnv->NewStringUTF(extras) : nullptr;
// Allocate space for the output argument.
jintArray uvMapArray = mEnv->NewIntArray(8);
// Call the Java-based material provider.
jobject materialInstance = mEnv->CallObjectMethod(mJavaProvider, mCreateMaterialInstance,
javaKey, uvMapArray, stringLabel);
javaKey, uvMapArray, stringLabel, stringExtras);
// Copy the UvMap results from the JVM array into the native array.
if (uvmap) {
@@ -125,6 +128,10 @@ public:
mEnv->DeleteLocalRef(stringLabel);
}
if (stringExtras) {
mEnv->DeleteLocalRef(stringExtras);
}
if (materialInstance == nullptr) {
return nullptr;
}
@@ -194,7 +201,6 @@ extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_AssetLoader_nDestroyAssetLoader(JNIEnv*, jclass,
jlong nativeLoader) {
AssetLoader* loader = (AssetLoader*) nativeLoader;
delete loader->getMaterialProvider();
NameComponentManager* names = loader->getNames();
AssetLoader::destroy(&loader);
delete names;
@@ -201,6 +201,44 @@ Java_com_google_android_filament_gltfio_FilamentAsset_nGetExtras(JNIEnv* env, jc
return val ? env->NewStringUTF(val) : nullptr;
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetSkinCount(JNIEnv* , jclass,
jlong nativeAsset) {
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
return (jint) asset->getSkinCount();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetSkinNames(JNIEnv* env, jclass,
jlong nativeAsset, jobjectArray result) {
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
jsize available = env->GetArrayLength(result);
for (int i = 0; i < available; ++i) {
const char* name = asset->getSkinNameAt(i);
if (name) {
env->SetObjectArrayElement(result, (jsize) i, env->NewStringUTF(name));
}
}
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetJointCountAt(JNIEnv* , jclass,
jlong nativeAsset, jint skinIndex) {
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
return (jint) asset->getJointCountAt(skinIndex);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetJointsAt(JNIEnv* env, jclass,
jlong nativeAsset, jint skinIndex, jintArray result) {
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
jsize available = env->GetArrayLength(result);
Entity* entities = (Entity*) env->GetIntArrayElements(result, nullptr);
std::copy_n(asset->getJointsAt(skinIndex),
std::min(available, (jsize) asset->getJointCountAt(skinIndex)), entities);
env->ReleaseIntArrayElements(result, (jint*) entities, 0);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetAnimator(JNIEnv* , jclass,
jlong nativeAsset) {
@@ -226,6 +264,49 @@ Java_com_google_android_filament_gltfio_FilamentAsset_nGetResourceUris(JNIEnv* e
}
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetMorphTargetCount(JNIEnv*, jclass,
jlong nativeAsset, jint entityId) {
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
Entity entity = Entity::import(entityId);
return (jint) asset->getMorphTargetCountAt(entity);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetMorphTargetNames(JNIEnv* env, jclass,
jlong nativeAsset, jint entityId, jobjectArray result) {
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
Entity entity = Entity::import(entityId);
for (int i = 0, n = asset->getMorphTargetCountAt(entity); i < n; ++i) {
const char* name = asset->getMorphTargetNameAt(entity, i);
env->SetObjectArrayElement(result, (jsize) i, env->NewStringUTF(name));
}
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetMaterialVariantCount(JNIEnv*, jclass,
jlong nativeAsset) {
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
return (jint) asset->getMaterialVariantCount();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nGetMaterialVariantNames(JNIEnv* env, jclass,
jlong nativeAsset, jobjectArray result) {
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
for (int i = 0; i < asset->getMaterialVariantCount(); ++i) {
const char* name = asset->getMaterialVariantName(i);
env->SetObjectArrayElement(result, (jsize) i, env->NewStringUTF(name));
}
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nApplyMaterialVariant(JNIEnv* env, jclass,
jlong nativeAsset, jint variantIndex) {
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
asset->applyMaterialVariant(variantIndex);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_FilamentAsset_nReleaseSourceData(JNIEnv* env, jclass,
jlong nativeAsset) {
@@ -54,3 +54,10 @@ Java_com_google_android_filament_gltfio_FilamentInstance_nGetAnimator(JNIEnv* ,
FilamentInstance* instance = (FilamentInstance*) nativeInstance;
return (jlong) instance->getAnimator();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_FilamentInstance_nApplyMaterialVariant(JNIEnv* env, jclass,
jlong nativeInstance, jint variantIndex) {
FilamentInstance* instance = (FilamentInstance*) nativeInstance;
instance->applyMaterialVariant(variantIndex);
}
@@ -19,6 +19,7 @@
#include <filament/Engine.h>
#include <gltfio/ResourceLoader.h>
#include <gltfio/TextureProvider.h>
#include <utils/Log.h>
@@ -114,3 +115,34 @@ Java_com_google_android_filament_gltfio_ResourceLoader_nAsyncCancelLoad(JNIEnv*,
ResourceLoader* loader = (ResourceLoader*) nativeLoader;
loader->asyncCancelLoad();
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_gltfio_ResourceLoader_nCreateStbProvider(JNIEnv*, jclass,
jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
return (jlong) createStbProvider(engine);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_gltfio_ResourceLoader_nCreateKtx2Provider(JNIEnv*, jclass,
jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
return (jlong) createKtx2Provider(engine);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_ResourceLoader_nDestroyTextureProvider(JNIEnv*, jclass,
jlong nativeProvider) {
TextureProvider* provider = (TextureProvider*) nativeProvider;
delete provider;
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_gltfio_ResourceLoader_nAddTextureProvider(JNIEnv* env, jclass,
jlong nativeLoader, jstring url, jlong nativeProvider) {
ResourceLoader* loader = (ResourceLoader*) nativeLoader;
TextureProvider* provider = (TextureProvider*) nativeProvider;
const char* cstring = env->GetStringUTFChars(url, nullptr);
loader->addTextureProvider(cstring, provider);
env->ReleaseStringUTFChars(url, cstring);
}
@@ -66,6 +66,15 @@ public class Animator {
nUpdateBoneMatrices(getNativeObject());
}
/**
* Pass the identity matrix into all bone nodes, useful for returning to the T pose.
*
* <p>NOTE: this operation is independent of <code>animation</code>.</p>
*/
public void resetBoneMatrices() {
nResetBoneMatrices(getNativeObject());
}
/**
* Returns the number of <code>animation</code> definitions in the glTF asset.
*/
@@ -109,6 +118,7 @@ public class Animator {
private static native void nApplyAnimation(long nativeAnimator, int index, float time);
private static native void nUpdateBoneMatrices(long nativeAnimator);
private static native void nResetBoneMatrices(long nativeAnimator);
private static native int nGetAnimationCount(long nativeAnimator);
private static native float nGetAnimationDuration(long nativeAnimator, int index);
private static native String nGetAnimationName(long nativeAnimator, int index);
@@ -45,7 +45,8 @@ import java.nio.Buffer;
*
* ...
*
* assetLoader = AssetLoader(engine, UbershaderLoader(engine), EntityManager.get())
* materialProvider = UbershaderLoader(engine)
* assetLoader = AssetLoader(engine, materialProvider, EntityManager.get())
*
* filamentAsset = assets.open("models/lucy.gltf").use { input -&gt;
* val bytes = ByteArray(input.available())
@@ -60,7 +61,6 @@ import java.nio.Buffer;
* }
* resourceLoader.loadResources(filamentAsset)
* resourceLoader.destroy()
* animator = asset.getAnimator()
* filamentAsset.releaseSourceData();
*
* scene.addEntities(filamentAsset.entities)
@@ -104,10 +104,12 @@ public class AssetLoader {
}
/**
* Frees all memory consumed by the native <code>AssetLoader</code> and its material cache.
* Frees all memory consumed by the native <code>AssetLoader</code>
*
* This does not not automatically free the cache of materials, nor
* does it free the entities for created assets (see destroyAsset).
*/
public void destroy() {
mMaterialCache.destroyMaterials();
nDestroyAssetLoader(mNativeObject);
mNativeObject = 0;
}
@@ -16,6 +16,7 @@
package com.google.android.filament.gltfio;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -197,11 +198,11 @@ public class FilamentAsset {
}
/**
* Creates or retrieves the <code>Animator</code> interface for this asset.
* Retrieves the <code>Animator</code> interface for this asset.
*
* <p>When calling this for the first time, this must be called after
* {@link ResourceLoader#loadResources}. When the asset is destroyed, its
* animator becomes invalid.</p>
* {@link ResourceLoader#loadResources} or {@link ResourceLoader#asyncBeginLoad}. When the asset
* is destroyed, its animator becomes invalid.</p>
*/
public @NonNull Animator getAnimator() {
if (mAnimator != null) {
@@ -215,6 +216,47 @@ public class FilamentAsset {
return mAnimator;
}
/**
* Gets the skin count of this asset.
*/
public int getSkinCount() {
return nGetSkinCount(getNativeObject());
}
/**
* Gets the skin name at skin index in this asset.
*/
public @NonNull String[] getSkinNames() {
String[] result = new String[getSkinCount()];
nGetSkinNames(getNativeObject(), result);
return result;
}
/**
* Gets the joint count at skin index in this asset.
*/
public int getJointCountAt(int skinIndex) {
return nGetJointCountAt(getNativeObject(), skinIndex);
}
/**
* Gets joints at skin index in this asset.
*/
public @NonNull @Entity int[] getJointsAt(int skinIndex) {
int[] result = new int[getJointCountAt(skinIndex)];
nGetJointsAt(getNativeObject(), skinIndex, result);
return result;
}
/**
* Gets the names of all morph targets in the given entity.
*/
public @NonNull String[] getMorphTargetNames(@Entity int entity) {
String[] names = new String[nGetMorphTargetCount(mNativeObject, entity)];
nGetMorphTargetNames(mNativeObject, entity, names);
return names;
}
/**
* Gets resource URIs for all externally-referenced buffers.
*/
@@ -224,12 +266,37 @@ public class FilamentAsset {
return uris;
}
/**
* Returns the names of all material variants.
*/
public @NonNull String[] getMaterialVariantNames() {
String[] names = new String[nGetMaterialVariantCount(mNativeObject)];
nGetMaterialVariantNames(mNativeObject, names);
return names;
}
/**
* Applies the given material variant to all primitives that it affects.
*
* This is efficient because it merely swaps around persistent MaterialInstances. If you change
* a material parameter while a certain variant is active, the updated value will be remembered
* after you re-apply that variant.
*
* If the asset is instanced, this affects all instances in the same way.
* To set the variant on an individual instance, use FilamentInstance#applyMaterialVariant.
*
* Ignored if variantIndex is out of bounds.
*/
public void applyMaterialVariant(@IntRange(from = 0) int variantIndex) {
nApplyMaterialVariant(getNativeObject(), variantIndex);
}
/**
* Reclaims CPU-side memory for URI strings, binding lists, and raw animation data.
*
* This should only be called after ResourceLoader#loadResources().
* If using Animator, this should be called after getAnimator().
* If this is an instanced asset, this prevents creation of new instances.
* This should only be called after ResourceLoader#loadResources() or
* ResourceLoader#asyncBeginLoad(). If this is an instanced asset, this prevents creation of new
* instances.
*/
public void releaseSourceData() {
nReleaseSourceData(mNativeObject);
@@ -260,10 +327,21 @@ public class FilamentAsset {
private static native int nGetMaterialInstanceCount(long nativeAsset);
private static native void nGetMaterialInstances(long nativeAsset, long[] nativeResults);
private static native int nGetMaterialVariantCount(long nativeAsset);
private static native void nGetMaterialVariantNames(long nativeAsset, String[] result);
private static native int nGetMorphTargetCount(long nativeAsset, int entity);
private static native void nGetMorphTargetNames(long nativeAsset, int entity, String[] result);
private static native void nGetBoundingBox(long nativeAsset, float[] box);
private static native String nGetName(long nativeAsset, int entity);
private static native String nGetExtras(long nativeAsset, int entity);
private static native long nGetAnimator(long nativeAsset);
private static native void nApplyMaterialVariant(long nativeAsset, int variantIndex);
private static native int nGetSkinCount(long nativeAsset);
private static native void nGetSkinNames(long nativeAsset, String[] result);
private static native int nGetJointCountAt(long nativeAsset, int skinIndex);
private static native void nGetJointsAt(long nativeAsset, int skinIndex, int[] result);
private static native int nGetResourceUriCount(long nativeAsset);
private static native void nGetResourceUris(long nativeAsset, String[] result);
private static native void nReleaseSourceData(long nativeAsset);
@@ -16,6 +16,7 @@
package com.google.android.filament.gltfio;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import com.google.android.filament.Entity;
@@ -74,10 +75,7 @@ public class FilamentInstance {
}
/**
* Creates or retrieves the <code>Animator</code> for this instance.
*
* <p>When calling this for the first time, this must be called after
* {@link ResourceLoader#loadResources}.</p>
* Retrieves the <code>Animator</code> for this instance.
*/
public @NonNull Animator getAnimator() {
if (mAnimator != null) {
@@ -87,8 +85,18 @@ public class FilamentInstance {
return mAnimator;
}
/**
* Applies the given material variant to all primitives in this instance.
*
* Ignored if variantIndex is out of bounds.
*/
void applyMaterialVariant(@IntRange(from = 0) int variantIndex) {
nApplyMaterialVariant(mNativeObject, variantIndex);
}
private static native int nGetRoot(long nativeAsset);
private static native int nGetEntityCount(long nativeAsset);
private static native void nGetEntities(long nativeAsset, int[] result);
private static native long nGetAnimator(long nativeAsset);
private static native void nApplyMaterialVariant(long nativeAsset, int variantIndex);
}
@@ -99,9 +99,10 @@ public interface MaterialProvider {
* @param uvmap Output argument that gets populated with a small table that maps from a glTF uv
* index to a Filament uv index (0 = UNUSED, 1 = UV0, 2 = UV1).
* @param label Optional tag that is not a part of the cache key.
* @param extras Optional extras as stringified JSON (not a part of the cache key).
*/
public @Nullable MaterialInstance createMaterialInstance(MaterialKey config,
@NonNull @Size(min = 8) int[] uvmap, @Nullable String label);
@NonNull @Size(min = 8) int[] uvmap, @Nullable String label, @Nullable String extras);
/**
* Creates and returns an array containing all cached materials.
@@ -126,4 +127,10 @@ public interface MaterialProvider {
* clients to take ownership of the cache if desired.
*/
public void destroyMaterials();
/**
* Frees memory consumed by the native <code>MaterialProvider</code>, but does not destroy
* cached materials.
*/
public void destroy();
}
@@ -35,6 +35,8 @@ import java.nio.Buffer;
*/
public class ResourceLoader {
private final long mNativeObject;
private final long mNativeStbProvider;
private final long mNativeKtx2Provider;
/**
* Constructs a resource loader tied to the given Filament engine.
@@ -46,6 +48,11 @@ public class ResourceLoader {
public ResourceLoader(@NonNull Engine engine) {
long nativeEngine = engine.getNativeObject();
mNativeObject = nCreateResourceLoader(nativeEngine, false, false, false);
mNativeStbProvider = nCreateStbProvider(nativeEngine);
mNativeKtx2Provider = nCreateKtx2Provider(nativeEngine);
nAddTextureProvider(mNativeObject, "image/jpeg", mNativeStbProvider);
nAddTextureProvider(mNativeObject, "image/png", mNativeStbProvider);
nAddTextureProvider(mNativeObject, "image/ktx2", mNativeKtx2Provider);
}
/**
@@ -63,6 +70,11 @@ public class ResourceLoader {
long nativeEngine = engine.getNativeObject();
mNativeObject = nCreateResourceLoader(nativeEngine, normalizeSkinningWeights,
recomputeBoundingBoxes, ignoreBindTransform);
mNativeStbProvider = nCreateStbProvider(nativeEngine);
mNativeKtx2Provider = nCreateKtx2Provider(nativeEngine);
nAddTextureProvider(mNativeObject, "image/jpeg", mNativeStbProvider);
nAddTextureProvider(mNativeObject, "image/png", mNativeStbProvider);
nAddTextureProvider(mNativeObject, "image/ktx2", mNativeKtx2Provider);
}
/**
@@ -70,6 +82,8 @@ public class ResourceLoader {
*/
public void destroy() {
nDestroyResourceLoader(mNativeObject);
nDestroyTextureProvider(mNativeStbProvider);
nDestroyTextureProvider(mNativeKtx2Provider);
}
/**
@@ -178,4 +192,9 @@ public class ResourceLoader {
private static native float nAsyncGetLoadProgress(long nativeLoader);
private static native void nAsyncUpdateLoad(long nativeLoader);
private static native void nAsyncCancelLoad(long nativeLoader);
private static native long nCreateStbProvider(long nativeEngine);
private static native long nCreateKtx2Provider(long nativeEngine);
private static native void nAddTextureProvider(long nativeLoader, String url, long nativeProvider);
private static native void nDestroyTextureProvider(long nativeProvider);
}
@@ -56,7 +56,7 @@ public class UbershaderLoader implements MaterialProvider {
}
public @Nullable MaterialInstance createMaterialInstance(MaterialKey config,
@NonNull @Size(min = 8) int[] uvmap, @Nullable String label) {
@NonNull @Size(min = 8) int[] uvmap, @Nullable String label, @Nullable String extras) {
long nativeMaterialInstance = nCreateMaterialInstance(mNativeObject, config, uvmap, label);
return nativeMaterialInstance == 0 ? null : new MaterialInstance(null, nativeMaterialInstance);
}
+1 -1
View File
@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.16.1
VERSION_NAME=1.21.3
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
+1 -1
View File
@@ -1,6 +1,6 @@
#Wed Nov 17 10:40:18 PST 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
@@ -36,6 +36,7 @@ import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileInputStream
import java.io.RandomAccessFile
import java.net.URI
import java.nio.Buffer
import java.nio.ByteBuffer
import java.nio.charset.StandardCharsets
@@ -118,7 +119,7 @@ class MainActivity : Activity() {
}
// FXAA is pretty cheap and helps a lot
view.antiAliasing = View.AntiAliasing.FXAA;
view.antiAliasing = View.AntiAliasing.FXAA
// ambient occlusion is the cheapest effect that adds a lot of quality
view.ambientOcclusionOptions = view.ambientOcclusionOptions.apply {
@@ -149,12 +150,12 @@ class MainActivity : Activity() {
val scene = modelViewer.scene
val ibl = "default_env"
readCompressedAsset("envs/$ibl/${ibl}_ibl.ktx").let {
scene.indirectLight = KTXLoader.createIndirectLight(engine, it)
scene.indirectLight = KTX1Loader.createIndirectLight(engine, it)
scene.indirectLight!!.intensity = 30_000.0f
viewerContent.indirectLight = modelViewer.scene.indirectLight
}
readCompressedAsset("envs/$ibl/${ibl}_skybox.ktx").let {
scene.skybox = KTXLoader.createSkybox(engine, it)
scene.skybox = KTX1Loader.createSkybox(engine, it)
}
}
@@ -217,13 +218,13 @@ class MainActivity : Activity() {
val sky = Skybox.Builder().environment(skyboxTexture).build(engine)
specularFilter.destroy();
equirectToCubemap.destroy();
context.destroy();
specularFilter.destroy()
equirectToCubemap.destroy()
context.destroy()
// destroy the previous IBl
engine.destroyIndirectLight(modelViewer.scene.indirectLight!!);
engine.destroySkybox(modelViewer.scene.skybox!!);
engine.destroyIndirectLight(modelViewer.scene.indirectLight!!)
engine.destroySkybox(modelViewer.scene.skybox!!)
modelViewer.scene.skybox = sky
modelViewer.scene.indirectLight = ibl
@@ -243,7 +244,7 @@ class MainActivity : Activity() {
val (zipStream, zipFile) = withContext(Dispatchers.IO) {
val file = File.createTempFile("incoming", "zip", cacheDir)
val raf = RandomAccessFile(file, "rw")
raf.getChannel().write(message.buffer);
raf.channel.write(message.buffer)
message.buffer = null
raf.seek(0)
Pair(FileInputStream(file), file)
@@ -296,21 +297,19 @@ class MainActivity : Activity() {
val gltfBuffer = pathToBufferMapping[gltfPath]!!
// The gltf is often not at the root level (e.g. if a folder is zipped) so
// we need to extract its path in order to resolve the embedded uri strings.
var gltfPrefix = gltfPath!!.substringBeforeLast('/', "")
if (gltfPrefix.isNotEmpty()) {
gltfPrefix += "/"
}
// In a zip file, the gltf file might be in the same folder as resources, or in a different
// folder. It is crucial to test against both of these cases. In any case, the resource
// paths are all specified relative to the location of the gltf file.
var prefix = URI(gltfPath!!).resolve(".")
withContext(Dispatchers.Main) {
if (gltfPath!!.endsWith(".glb")) {
modelViewer.loadModelGlb(gltfBuffer)
} else {
modelViewer.loadModelGltf(gltfBuffer) { uri ->
val path = gltfPrefix + uri
val path = prefix.resolve(uri).toString()
if (!pathToBufferMapping.contains(path)) {
Log.e(TAG, "Could not find $path in the zip.")
Log.e(TAG, "Could not find '$uri' in zip using prefix '$prefix' and base path '${gltfPath!!}'")
setStatusText("Zip is missing $path")
}
pathToBufferMapping[path]
@@ -343,12 +342,10 @@ class MainActivity : Activity() {
clearStatusText()
titlebarHint.text = message.label
CoroutineScope(Dispatchers.IO).launch {
if (message.label.endsWith(".zip")) {
loadZip(message)
} else if (message.label.endsWith(".hdr")) {
loadHdr(message)
} else {
loadGlb(message)
when {
message.label.endsWith(".zip") -> loadZip(message)
message.label.endsWith(".hdr") -> loadHdr(message)
else -> loadGlb(message)
}
}
}
@@ -79,8 +79,6 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
// Performs the rendering and schedules new frames
private val frameScheduler = FrameCallback()
private var externalTextureID: Int = 0
@RequiresApi(30)
class Api30Impl {
companion object {
@@ -103,8 +101,6 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
setupView()
setupScene()
externalTextureID = createExternalTexture()
@Suppress("deprecation")
val display = if (Build.VERSION.SDK_INT >= 30) {
Api30Impl.getDisplay(this)
@@ -112,7 +108,7 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
windowManager.defaultDisplay!!
}
streamHelper = StreamHelper(engine, materialInstance, display, externalTextureID)
streamHelper = StreamHelper(engine, materialInstance, display)
this.title = streamHelper.getTestName()
}
@@ -445,31 +441,4 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
check(EGL14.eglMakeCurrent(display, surface, surface, context)) { "Error making GL context." }
return context
}
private fun createExternalTexture(): Int {
val textures = IntArray(1)
GLES30.glGenTextures(1, textures, 0)
val result = textures[0]
val textureTarget = GLES11Ext.GL_TEXTURE_EXTERNAL_OES
GLES30.glBindTexture(textureTarget, result)
GLES30.glTexParameteri(textureTarget, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
GLES30.glTexParameteri(textureTarget, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
GLES30.glTexParameteri(textureTarget, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST)
GLES30.glTexParameteri(textureTarget, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_NEAREST)
if (!GLES30.glIsTexture(result)) {
throw RuntimeException("OpenGL error: $result is an invalid texture.")
}
val error = GLES30.glGetError()
if (error != GLES30.GL_NO_ERROR) {
val errorString = GLU.gluErrorString(error)
throw RuntimeException("OpenGL error: $errorString!")
}
return result
}
}
@@ -37,7 +37,6 @@ class StreamHelper(
private val filamentEngine: Engine,
private val filamentMaterial: MaterialInstance,
private val display: Display,
private val externalTextureId: Int
) {
/**
* The StreamSource configures the source data for the texture.
@@ -51,7 +50,6 @@ class StreamHelper(
*/
enum class StreamSource {
CANVAS_STREAM_NATIVE, // copy-free but does not guarantee synchronization
CANVAS_STREAM_TEXID, // synchronized but incurs a copy
CANVAS_STREAM_ACQUIRED, // synchronized and copy-free
}
@@ -127,10 +125,6 @@ class StreamHelper(
surface.unlockCanvasAndPost(canvas)
if (streamSource == StreamSource.CANVAS_STREAM_TEXID) {
surfaceTexture!!.updateTexImage()
}
if (streamSource == StreamSource.CANVAS_STREAM_ACQUIRED) {
val image = imageReader!!.acquireLatestImage()
filamentStream!!.setAcquiredImage(
@@ -146,7 +140,7 @@ class StreamHelper(
fun nextTest() {
stopTest()
streamSource = StreamSource.values()[(streamSource.ordinal + 1) % 3]
streamSource = StreamSource.values()[(streamSource.ordinal + 1) % StreamSource.values().size]
startTest()
}
@@ -213,23 +207,6 @@ class StreamHelper(
filamentTexture.setExternalStream(filamentEngine, filamentStream!!)
}
if (streamSource == StreamSource.CANVAS_STREAM_TEXID) {
// Create the Android surface that will hold the canvas image.
surfaceTexture = SurfaceTexture(externalTextureId)
surfaceTexture!!.setDefaultBufferSize(resolution.width, resolution.height)
canvasSurface = Surface(surfaceTexture)
// Create the Filament Stream object that gets bound to the Texture.
filamentStream = Stream.Builder()
.stream(externalTextureId.toLong())
.width(resolution.width)
.height(resolution.height)
.build(filamentEngine)
filamentTexture.setExternalStream(filamentEngine, filamentStream!!)
}
if (streamSource == StreamSource.CANVAS_STREAM_ACQUIRED) {
filamentStream = Stream.Builder()
.width(resolution.width)
@@ -281,7 +281,7 @@ class MainActivity : Activity() {
// Stop the animation and any pending frame
choreographer.removeFrameCallback(frameScheduler)
animator.cancel();
animator.cancel()
// Always detach the surface before destroying the engine
uiHelper.detach()
@@ -328,11 +328,11 @@ class MainActivity : Activity() {
override fun onNativeWindowChanged(surface: Surface) {
swapChain?.let { engine.destroySwapChain(it) }
swapChain = engine.createSwapChain(surface, uiHelper.swapChainFlags)
displayHelper.attach(renderer, surfaceView.display);
displayHelper.attach(renderer, surfaceView.display)
}
override fun onDetachedFromSurface() {
displayHelper.detach();
displayHelper.detach()
swapChain?.let {
engine.destroySwapChain(it)
// Required to ensure we don't return before Filament is done executing the
@@ -353,6 +353,7 @@ class MainActivity : Activity() {
}
}
@Suppress("SameParameterValue")
private fun readUncompressedAsset(assetName: String): ByteBuffer {
assets.openFd(assetName).use { fd ->
val input = fd.createInputStream()
Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

+12 -10
View File
@@ -98,9 +98,9 @@ function print_matdbg_help {
echo ""
echo "FOR ANDROID BUILDS:"
echo ""
echo "1) The most reliable way to enable matdbg is to bypass Gradle and"
echo " directly modify the appropriate two lines in the following file:"
echo " ./android/filament-android/CMakeLists.txt"
echo "1) For Android Studio builds, make sure to set:"
echo " -Pcom.google.android.filament.matdbg"
echo " option in Preferences > Build > Compiler > Command line options."
echo ""
echo "2) The port number is hardcoded to 8081 so you will need to do:"
echo " adb forward tcp:8081 tcp:8081"
@@ -156,6 +156,7 @@ VULKAN_ANDROID_GRADLE_OPTION=""
SWIFTSHADER_OPTION="-DFILAMENT_USE_SWIFTSHADER=OFF"
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=OFF"
MATDBG_GRADLE_OPTION=""
IOS_BUILD_SIMULATOR=false
BUILD_UNIVERSAL_LIBRARIES=false
@@ -303,7 +304,7 @@ function build_webgl_with_target {
}
function build_webgl {
# For the host tools, supress install and always use Release.
# For the host tools, suppress install and always use Release.
local old_install_command=${INSTALL_COMMAND}; INSTALL_COMMAND=
local old_issue_debug_build=${ISSUE_DEBUG_BUILD}; ISSUE_DEBUG_BUILD=false
local old_issue_release_build=${ISSUE_RELEASE_BUILD}; ISSUE_RELEASE_BUILD=true
@@ -402,7 +403,7 @@ function ensure_android_build {
function build_android {
ensure_android_build
# Supress intermediate desktop tools install
# Suppress intermediate desktop tools install
local old_install_command=${INSTALL_COMMAND}
INSTALL_COMMAND=
@@ -456,6 +457,7 @@ function build_android {
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
${VULKAN_ANDROID_GRADLE_OPTION} \
${MATDBG_GRADLE_OPTION} \
:filament-android:assembleDebug \
:gltfio-android:assembleDebug \
:filament-utils-android:assembleDebug
@@ -487,8 +489,7 @@ function build_android {
cp gltfio-android/build/outputs/aar/gltfio-android-full-debug.aar ../out/gltfio-android-debug.aar
echo "Installing out/filament-utils-android-debug.aar..."
cp filament-utils-android/build/outputs/aar/filament-utils-android-lite-debug.aar ../out/
cp filament-utils-android/build/outputs/aar/filament-utils-android-full-debug.aar ../out/filament-utils-android-debug.aar
cp filament-utils-android/build/outputs/aar/filament-utils-android-debug.aar ../out/filament-utils-android-debug.aar
if [[ "${BUILD_ANDROID_SAMPLES}" == "true" ]]; then
for sample in ${ANDROID_SAMPLES}; do
@@ -505,6 +506,7 @@ function build_android {
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
${VULKAN_ANDROID_GRADLE_OPTION} \
${MATDBG_GRADLE_OPTION} \
:filament-android:assembleRelease \
:gltfio-android:assembleRelease \
:filament-utils-android:assembleRelease
@@ -536,8 +538,7 @@ function build_android {
cp gltfio-android/build/outputs/aar/gltfio-android-full-release.aar ../out/gltfio-android-release.aar
echo "Installing out/filament-utils-android-release.aar..."
cp filament-utils-android/build/outputs/aar/filament-utils-android-lite-release.aar ../out/
cp filament-utils-android/build/outputs/aar/filament-utils-android-full-release.aar ../out/filament-utils-android-release.aar
cp filament-utils-android/build/outputs/aar/filament-utils-android-release.aar ../out/filament-utils-android-release.aar
if [[ "${BUILD_ANDROID_SAMPLES}" == "true" ]]; then
for sample in ${ANDROID_SAMPLES}; do
@@ -600,7 +601,7 @@ function archive_ios {
}
function build_ios {
# Supress intermediate desktop tools install
# Suppress intermediate desktop tools install
local old_install_command=${INSTALL_COMMAND}
INSTALL_COMMAND=
@@ -756,6 +757,7 @@ while getopts ":hacCfijmp:q:uvslwtdk:" opt; do
d)
PRINT_MATDBG_HELP=true
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=ON, -DFILAMENT_DISABLE_MATOPT=ON, -DFILAMENT_BUILD_FILAMAT=ON"
MATDBG_GRADLE_OPTION="-Pcom.google.android.filament.matdbg"
;;
f)
ISSUE_CMAKE_ALWAYS=true
+2 -2
View File
@@ -52,11 +52,11 @@ if [[ ! -d "${ANDROID_HOME}/ndk/$FILAMENT_NDK_VERSION" ]]; then
${ANDROID_HOME}/tools/bin/sdkmanager "ndk;$FILAMENT_NDK_VERSION" > /dev/null
fi
# Only build 1 32 bit and 1 64 bit target during presubmit to cut down build times
# Only build 1 64 bit target during presubmit to cut down build times during presubmit
# Continuous builds will build everything
ANDROID_ABIS=
if [[ "$TARGET" == "presubmit" ]]; then
ANDROID_ABIS="-q arm64-v8a,x86"
ANDROID_ABIS="-q arm64-v8a"
fi
# Build the Android sample-gltf-viewer APK during release.
+14
View File
@@ -0,0 +1,14 @@
setuptools==40.6.2
wheel==0.37.1
certifi==2021.10.8
cffi==1.15.0
charset-normalizer==2.0.12
Deprecated==1.2.13
idna==3.3
pycparser==2.21
PyGithub==1.55
PyJWT==2.3.0
PyNaCl==1.5.0
requests==2.27.1
urllib3==1.26.9
wrapt==1.14.0
+1
View File
@@ -11,3 +11,4 @@ tools/cmgen/test_cmgen compare
tools/glslminifier/test_glslminifier
libs/filameshio/test_filameshio
libs/camutils/test_camutils
libs/ktxreader/test_ktxreader
+19
View File
@@ -12,6 +12,25 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# requirements.txt created via:
#
# pip3 install virtualenv
# python3 -m venv env
# pip3 install PyGithub
# pip3 install wheel
# --all includes wheel and setuputils, which is needed for GitHub Actions
# pip3 freeze --all > requirements.txt
# Manually move 'setuptools' and 'wheel' lines to the beginning of the file.
# Manually remove the 'pip' line.
#
# Requirements are installed in GitHub Actions via:
# xargs -L 1 sudo pip3 install < build/common/requirements.txt
# xargs must be used because the ordering of the dependencies matters (namely, setuptools).
# sudo must be used to uninstall non-matching versions of packages.
# pip is removed to avoid conflicts with the pre-installed pip version on Actions.
# This technique does not work with Windows, unfortunately.
from github import Github
import os, sys
+2
View File
@@ -3,4 +3,6 @@
curl -OL https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-mac.zip
unzip -q ninja-mac.zip
chmod +x ninja
# Install ninja globally for AGP
cp ninja /usr/local/bin
export PATH="$PWD:$PATH"
+11 -3
View File
@@ -1,7 +1,15 @@
#!/bin/bash
if [ `uname` == "Linux" ];then
curl -OL https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-linux.zip
unzip -q ninja-linux.zip
elif [ `uname` == "Darwin" ];then
curl -OL https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-mac.zip
unzip -q ninja-mac.zip
else
echo "Unsupported OS"
exit 1
fi
curl -OL https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-mac.zip
unzip -q ninja-mac.zip
chmod +x ninja
export PATH="$PWD:$PATH"
@@ -9,7 +17,7 @@ export PATH="$PWD:$PATH"
# npm install -g typescript
# Install emscripten.
curl -L https://github.com/emscripten-core/emsdk/archive/2.0.23.zip > emsdk.zip
curl -L https://github.com/emscripten-core/emsdk/archive/refs/tags/3.1.9.zip > emsdk.zip
unzip emsdk.zip ; mv emsdk-* emsdk ; cd emsdk
./emsdk install latest
./emsdk activate latest
+53 -24
View File
@@ -106,15 +106,16 @@ counter-increment: h6;margin-right:10px}
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:depthwrite" class="level3"><span class="tocNumber">4.2.19&nbsp; </span>Rasterization: depthWrite</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:depthculling" class="level3"><span class="tocNumber">4.2.20&nbsp; </span>Rasterization: depthCulling</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/rasterization:doublesided" class="level3"><span class="tocNumber">4.2.21&nbsp; </span>Rasterization: doubleSided</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:shadowmultiplier" class="level3"><span class="tocNumber">4.2.22&nbsp; </span>Lighting: shadowMultiplier</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:transparentshadow" class="level3"><span class="tocNumber">4.2.23&nbsp; </span>Lighting: transparentShadow</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:clearcoatiorchange" class="level3"><span class="tocNumber">4.2.24&nbsp; </span>Lighting: clearCoatIorChange</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:multibounceambientocclusion" class="level3"><span class="tocNumber">4.2.25&nbsp; </span>Lighting: multiBounceAmbientOcclusion</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:specularambientocclusion" class="level3"><span class="tocNumber">4.2.26&nbsp; </span>Lighting: specularAmbientOcclusion</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasing" class="level3"><span class="tocNumber">4.2.27&nbsp; </span>Anti-aliasing: specularAntiAliasing</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance" class="level3"><span class="tocNumber">4.2.28&nbsp; </span>Anti-aliasing: specularAntiAliasingVariance</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold" class="level3"><span class="tocNumber">4.2.29&nbsp; </span>Anti-aliasing: specularAntiAliasingThreshold</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/shading:customsurfaceshading" class="level3"><span class="tocNumber">4.2.30&nbsp; </span>Shading: customSurfaceShading</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:reflections" class="level3"><span class="tocNumber">4.2.22&nbsp; </span>Lighting: reflections</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:shadowmultiplier" class="level3"><span class="tocNumber">4.2.23&nbsp; </span>Lighting: shadowMultiplier</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:transparentshadow" class="level3"><span class="tocNumber">4.2.24&nbsp; </span>Lighting: transparentShadow</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:clearcoatiorchange" class="level3"><span class="tocNumber">4.2.25&nbsp; </span>Lighting: clearCoatIorChange</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:multibounceambientocclusion" class="level3"><span class="tocNumber">4.2.26&nbsp; </span>Lighting: multiBounceAmbientOcclusion</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/lighting:specularambientocclusion" class="level3"><span class="tocNumber">4.2.27&nbsp; </span>Lighting: specularAmbientOcclusion</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasing" class="level3"><span class="tocNumber">4.2.28&nbsp; </span>Anti-aliasing: specularAntiAliasing</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance" class="level3"><span class="tocNumber">4.2.29&nbsp; </span>Anti-aliasing: specularAntiAliasingVariance</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold" class="level3"><span class="tocNumber">4.2.30&nbsp; </span>Anti-aliasing: specularAntiAliasingThreshold</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/materialblock/shading:customsurfaceshading" class="level3"><span class="tocNumber">4.2.31&nbsp; </span>Shading: customSurfaceShading</a><br>
&nbsp;&nbsp;<a href="#materialdefinitions/vertexblock" class="level2"><span class="tocNumber">4.3&nbsp; </span>Vertex block</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#materialdefinitions/vertexblock/materialvertexinputs" class="level3"><span class="tocNumber">4.3.1&nbsp; </span>Material vertex inputs</a><br>
&nbsp;&nbsp;<a href="#materialdefinitions/fragmentblock" class="level2"><span class="tocNumber">4.4&nbsp; </span>Fragment block</a><br>
@@ -773,7 +774,7 @@ and with (right)</span></center></div></center>
The <code>bentNormal</code> property defines the average unoccluded direction at a point on the surface. It is
used to improve the accuracy of indirect lighting. Bent normals can also improve the quality of
specular ambient occlusion (see section <a href="#toc4.2.26">4.2.26</a> about
specular ambient occlusion (see section <a href="#toc4.2.27">4.2.27</a> about
<code>specularAmbientOcclusion</code>).
</p><p>
@@ -1959,15 +1960,43 @@ and sorting issues are minimized or eliminated</span></center></div></center>
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
</p></dd><dt>Description</dt><dd><p> Enables two-sided rendering and its capability to be toggled at run time. When set to <code>true</code>,
<code>culling</code> is automatically set to <code>none</code>; if the triangle is back-facing, the triangle's
normal is flipped to become front-facing. When explicitly set to <code>false</code>, this allows the
double-sidedness to be toggled at run time.
</p></dd><dt>Description</dt><dd><p> Only available in the <code>unlit</code> shading model. If this property is enabled, the final color
computed by the material is multiplied by the shadowing factor (or visibility). This allows to
create transparent shadow-receiving objects (for instance an invisible ground plane in AR).
This is only supported with shadows from directional lights.
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> doubleSided : <span class="hljs-literal">true</span></span>
<span class="line"> name : <span class="hljs-string">"Invisible shadow plane"</span>,</span>
<span class="line"> shadingModel : unlit,</span>
<span class="line"> shadowMultiplier : <span class="hljs-literal">true</span>,</span>
<span class="line"> blending : transparent</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">fragment {</span>
<span class="line"> void material(inout MaterialInputs material) {</span>
<span class="line"> prepareMaterial(material);</span>
<span class="line"> <span class="hljs-comment">// baseColor defines the color and opacity of the final shadow</span></span>
<span class="line"> material.baseColor = vec4(0.0, 0.0, 0.0, 0.7);</span>
<span class="line"> }</span>
<span class="line">}</span></code></pre>
<a class="target" name="lighting:shadowmultiplier">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:shadowmultiplier">&nbsp;</a><a class="target" name="toc4.2.22">&nbsp;</a><h3>Lighting: shadowMultiplier</h3>
<a class="target" name="lighting:reflections">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:reflections">&nbsp;</a><a class="target" name="toc4.2.22">&nbsp;</a><h3>Lighting: reflections</h3>
<p>
</p><dl><dt>Type</dt><dd><p> <code>string</code>
</p></dd><dt>Value</dt><dd><p> <code>default</code> or <code>screenspace</code>. Defaults to <code>default</code>.
</p></dd><dt>Description</dt><dd><p> Controls the source of specular reflections for this material. When this property is set to
<code>default</code>, reflections only come image-based lights. When this property is set to
<code>screenspace</code>, reflections come from the screen space's color buffer in addition to
image-based lights.
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> name : <span class="hljs-string">"Glossy metal"</span>,</span>
<span class="line"> reflections : screenspace</span>
<span class="line">}</span></code></pre>
<a class="target" name="lighting:shadowmultiplier">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:shadowmultiplier">&nbsp;</a><a class="target" name="toc4.2.23">&nbsp;</a><h3>Lighting: shadowMultiplier</h3>
<p>
@@ -1994,7 +2023,7 @@ and sorting issues are minimized or eliminated</span></center></div></center>
<span class="line"> material.baseColor = vec4(0.0, 0.0, 0.0, 0.7);</span>
<span class="line"> }</span>
<span class="line">}</span></code></pre>
<a class="target" name="lighting:transparentshadow">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:transparentshadow">&nbsp;</a><a class="target" name="toc4.2.23">&nbsp;</a><h3>Lighting: transparentShadow</h3>
<a class="target" name="lighting:transparentshadow">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:transparentshadow">&nbsp;</a><a class="target" name="toc4.2.24">&nbsp;</a><h3>Lighting: transparentShadow</h3>
<p>
@@ -2028,7 +2057,7 @@ radius of 4. Model <a href="https://sketchfab.com/3d-models/bottle-of-water-48fd
by <a href="https://sketchfab.com/person-x">T-Art</a>.</span></center></div></center>
<p></p>
<a class="target" name="lighting:clearcoatiorchange">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:clearcoatiorchange">&nbsp;</a><a class="target" name="toc4.2.24">&nbsp;</a><h3>Lighting: clearCoatIorChange</h3>
<a class="target" name="lighting:clearcoatiorchange">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:clearcoatiorchange">&nbsp;</a><a class="target" name="toc4.2.25">&nbsp;</a><h3>Lighting: clearCoatIorChange</h3>
<p>
@@ -2050,7 +2079,7 @@ with <code>clearCoatIorChange</code> enabled (left) and disabled
(right).</span></center></div></center>
<p></p>
<a class="target" name="lighting:multibounceambientocclusion">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:multibounceambientocclusion">&nbsp;</a><a class="target" name="toc4.2.25">&nbsp;</a><h3>Lighting: multiBounceAmbientOcclusion</h3>
<a class="target" name="lighting:multibounceambientocclusion">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:multibounceambientocclusion">&nbsp;</a><a class="target" name="toc4.2.26">&nbsp;</a><h3>Lighting: multiBounceAmbientOcclusion</h3>
<p>
@@ -2079,7 +2108,7 @@ occclusion enabled (left) and disabled (right).</span></center></div></center>
occclusion enabled and disabled.</span></center></div></center>
<p></p>
<a class="target" name="lighting:specularambientocclusion">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:specularambientocclusion">&nbsp;</a><a class="target" name="toc4.2.26">&nbsp;</a><h3>Lighting: specularAmbientOcclusion</h3>
<a class="target" name="lighting:specularambientocclusion">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/lighting:specularambientocclusion">&nbsp;</a><a class="target" name="toc4.2.27">&nbsp;</a><h3>Lighting: specularAmbientOcclusion</h3>
<p>
@@ -2105,7 +2134,7 @@ occclusion enabled and disabled.</span></center></div></center>
particularly visible under the hose.</span></center></div></center>
<p></p>
<a class="target" name="anti-aliasing:specularantialiasing">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasing">&nbsp;</a><a class="target" name="toc4.2.27">&nbsp;</a><h3>Anti-aliasing: specularAntiAliasing</h3>
<a class="target" name="anti-aliasing:specularantialiasing">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasing">&nbsp;</a><a class="target" name="toc4.2.28">&nbsp;</a><h3>Anti-aliasing: specularAntiAliasing</h3>
<p>
@@ -2122,7 +2151,7 @@ particularly visible under the hose.</span></center></div></center>
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> specularAntiAliasing : <span class="hljs-literal">true</span></span>
<span class="line">}</span></code></pre>
<a class="target" name="anti-aliasing:specularantialiasingvariance">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance">&nbsp;</a><a class="target" name="toc4.2.28">&nbsp;</a><h3>Anti-aliasing: specularAntiAliasingVariance</h3>
<a class="target" name="anti-aliasing:specularantialiasingvariance">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance">&nbsp;</a><a class="target" name="toc4.2.29">&nbsp;</a><h3>Anti-aliasing: specularAntiAliasingVariance</h3>
<p>
@@ -2137,7 +2166,7 @@ particularly visible under the hose.</span></center></div></center>
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> specularAntiAliasingVariance : <span class="hljs-number">0.2</span></span>
<span class="line">}</span></code></pre>
<a class="target" name="anti-aliasing:specularantialiasingthreshold">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold">&nbsp;</a><a class="target" name="toc4.2.29">&nbsp;</a><h3>Anti-aliasing: specularAntiAliasingThreshold</h3>
<a class="target" name="anti-aliasing:specularantialiasingthreshold">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold">&nbsp;</a><a class="target" name="toc4.2.30">&nbsp;</a><h3>Anti-aliasing: specularAntiAliasingThreshold</h3>
<p>
@@ -2151,7 +2180,7 @@ particularly visible under the hose.</span></center></div></center>
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
<span class="line"> specularAntiAliasingThreshold : <span class="hljs-number">0.1</span></span>
<span class="line">}</span></code></pre>
<a class="target" name="shading:customsurfaceshading">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/shading:customsurfaceshading">&nbsp;</a><a class="target" name="toc4.2.30">&nbsp;</a><h3>Shading: customSurfaceShading</h3>
<a class="target" name="shading:customsurfaceshading">&nbsp;</a><a class="target" name="materialdefinitions/materialblock/shading:customsurfaceshading">&nbsp;</a><a class="target" name="toc4.2.31">&nbsp;</a><h3>Shading: customSurfaceShading</h3>
<p>
+47 -11
View File
@@ -1050,7 +1050,7 @@ Type
: array of `string`
Value
: Each entry must be any of `dynamicLighting`, `directionalLighting`, `shadowReceiver` or `skinning`.
: Each entry must be any of `dynamicLighting`, `directionalLighting`, `shadowReceiver`,`skinning` or `ssr`.
Description
: Used to specify a list of shader variants that the application guarantees will never be
@@ -1068,6 +1068,7 @@ Description of the variants:
- `skinning`, used when an object is animated using GPU skinning
- `fog`, used when global fog is applied to the scene
- `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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
@@ -1278,8 +1279,9 @@ Description
- **Screen**: blending is enabled. Effectively the opposite of the `multiply`, the content of the
render target is brightened.
- **Masked**: blending is disabled. This blending mode enables alpha masking. The alpha channel
of the material's output defines whether a fragment is discarded or not. See the maskThreshold
section for more information.
of the material's output defines whether a fragment is discarded or not. Additionally,
ALPHA_TO_COVERAGE is enabled for non-translucent views. See the maskThreshold section for more
information.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
@@ -1363,8 +1365,9 @@ Value
Description
: Sets the minimum alpha value a fragment must have to not be discarded when the `blending` mode
is set to `masked`. When the blending mode is not `masked`, this value is ignored. This value
can be used to controlled the appearance of alpha-masked objects.
is set to `masked`. If the fragment is not discarded, its source alpha is set to 1. When the
blending mode is not `masked`, this value is ignored. This value can be used to controlled the
appearance of alpha-masked objects.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
@@ -1500,14 +1503,46 @@ Value
: `true` or `false`. Defaults to `false`.
Description
: Enables two-sided rendering and its capability to be toggled at run time. When set to `true`,
`culling` is automatically set to `none`; if the triangle is back-facing, the triangle's
normal is flipped to become front-facing. When explicitly set to `false`, this allows the
double-sidedness to be toggled at run time.
: Only available in the `unlit` shading model. If this property is enabled, the final color
computed by the material is multiplied by the shadowing factor (or visibility). This allows to
create transparent shadow-receiving objects (for instance an invisible ground plane in AR).
This is only supported with shadows from directional lights.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
doubleSided : true
name : "Invisible shadow plane",
shadingModel : unlit,
shadowMultiplier : true,
blending : transparent
}
fragment {
void material(inout MaterialInputs material) {
prepareMaterial(material);
// baseColor defines the color and opacity of the final shadow
material.baseColor = vec4(0.0, 0.0, 0.0, 0.7);
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### Lighting: reflections
Type
: `string`
Value
: `default` or `screenspace`. Defaults to `default`.
Description
: Controls the source of specular reflections for this material. When this property is set to
`default`, reflections only come image-based lights. When this property is set to
`screenspace`, reflections come from the screen space's color buffer in addition to
image-based lights.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
name : "Glossy metal",
reflections : screenspace
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2134,7 +2169,7 @@ type aliases:
Name | Type | Description
:-----------------------------------|:--------:|:------------------------------------
**getResolution()** | float4 | Resolution of the view in pixels: `width`, `height`, `1 / width`, `1 / height`
**getResolution()** | float4 | Dimensions of the view's effective viewport in pixels: `width`, `height`, `1 / width`, `1 / height`. This might be different from `View::getViewport()` for instance because of added rendering guard-bands. This can be used in conjunction with `getNormalizedViewportCoord()` to generate pixel coordinates.
**getWorldCameraPosition()** | float3 | Position of the camera/eye in world space
**getWorldOffset()** | float3 | The shift required to obtain API-level world space
**getTime()** | float | Current time as a remainder of 1 second. Yields a value between 0 and 1
@@ -2305,6 +2340,7 @@ variants:
- `skinning`, used when an object is animated using GPU skinning or vertex morphing
- `fog`, used when global fog is applied to the scene
- `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
Example:
```
File diff suppressed because it is too large Load Diff
+48 -19
View File
File diff suppressed because one or more lines are too long
Binary file not shown.
+1 -1
View File
@@ -12,7 +12,7 @@
</head>
<body>
<canvas></canvas>
<script src="//unpkg.com/filament@1.15.0/filament.js"></script>
<script src="filament.js"></script>
<script src="//unpkg.com/gl-matrix@2.8.1"></script>
<script src="//unpkg.com/gltumble"></script>
<script src="tutorial_redball.js"></script>
+1 -1
View File
@@ -12,7 +12,7 @@
</head>
<body>
<canvas></canvas>
<script src="//unpkg.com/filament@1.15.0/filament.js"></script>
<script src="filament.js"></script>
<script src="//unpkg.com/gl-matrix@2.8.1"></script>
<script src="//unpkg.com/gltumble"></script>
<script src="tutorial_suzanne.js"></script>
+1 -1
View File
@@ -12,7 +12,7 @@
</head>
<body>
<canvas></canvas>
<script src="//unpkg.com/filament@1.15.0/filament.js"></script>
<script src="filament.js"></script>
<script src="//unpkg.com/gl-matrix@2.8.1"></script>
<script src="//unpkg.com/gltumble"></script>
<script src="tutorial_triangle.js"></script>
+66 -28
View File
File diff suppressed because one or more lines are too long
Binary file not shown.
+1 -1
View File
@@ -113,7 +113,7 @@ class App {
this.view = engine.createView();
this.view.setVignetteOptions({ midPoint: 0.8, enabled: true });
this.view.setBloomOptions({ stength: 0.2, enabled: true });
this.view.setBloomOptions({ strength: 0.2, enabled: true });
this.view.setCamera(this.camera);
this.view.setScene(this.scene);
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+28 -13
View File
@@ -64,7 +64,7 @@
<td align="left">Array of 16-bit or 32-bit unsigned integers consumed by the GPU.</td>
</tr>
<tr>
<td align="left"><a href="#KtxBundle">KtxBundle</a></td>
<td align="left"><a href="#Ktx1Bundle">Ktx1Bundle</a></td>
<td align="left">In-memory representation of a KTX file.</td>
</tr>
<tr>
@@ -583,6 +583,11 @@
<li><em>overrides</em> Dictionary with one or more of the following properties: enabled, sampleCount, customResolve.</li>
</ul>
</li>
<li><strong>engine.setScreenSpaceReflectionsOptions(overrides)</strong>
<ul>
<li><em>overrides</em> Dictionary with one or more of the following properties: thickness, bias, maxDistance, stride, enabled.</li>
</ul>
</li>
<li><strong>engine.setShadowOptions(instance, overrides)</strong>
<ul>
<li><em>instance</em> Instance of a light component obtained from <code>getInstance</code>.</li>
@@ -662,63 +667,63 @@ as quaternions.</li>
</ul>
</div>
<div class='classdoc'>
<h2>class <a id='KtxBundle' href='#KtxBundle'>KtxBundle</a></h2>
<h2>class <a id='Ktx1Bundle' href='#Ktx1Bundle'>Ktx1Bundle</a></h2>
<p>In-memory representation of a KTX file.</p>
<ul>
<li><strong>ktxBundle.getArrayLength()</strong>
<li><strong>ktx1Bundle.getArrayLength()</strong>
<ul>
<li>Obtains length of the texture array.</li>
<li><em>returns</em> The number of elements in the texture array</li>
</ul>
</li>
<li><strong>ktxBundle.getCompressedPixelDataType()</strong>
<li><strong>ktx1Bundle.getCompressedPixelDataType()</strong>
<ul>
<li><em>returns</em> <a href="#CompressedPixelDataType">CompressedPixelDataType</a></li>
</ul>
</li>
<li><strong>ktxBundle.getInternalFormat(srgb)</strong>
<li><strong>ktx1Bundle.getInternalFormat(srgb)</strong>
<ul>
<li><em>srgb</em> boolean that forces the resulting format to SRGB if possible.</li>
<li><em>returns</em> <a href="#Texture%24InternalFormat">Texture$InternalFormat</a></li>
</ul>
</li>
<li><strong>ktxBundle.getMetadata(key)</strong>
<li><strong>ktx1Bundle.getMetadata(key)</strong>
<ul>
<li>Obtains arbitrary metadata from the KTX file.</li>
<li><em>key</em> string</li>
<li><em>returns</em> string</li>
</ul>
</li>
<li><strong>ktxBundle.getPixelDataFormat()</strong>
<li><strong>ktx1Bundle.getPixelDataFormat()</strong>
<ul>
<li><em>returns</em> <a href="#PixelDataFormat">PixelDataFormat</a></li>
</ul>
</li>
<li><strong>ktxBundle.getPixelDataType()</strong>
<li><strong>ktx1Bundle.getPixelDataType()</strong>
<ul>
<li><em>returns</em> <a href="#PixelDataType">PixelDataType</a></li>
</ul>
</li>
<li><strong>ktxBundle.info()</strong>
<li><strong>ktx1Bundle.info()</strong>
<ul>
<li>Obtains properties of the KTX header.</li>
<li><em>returns</em> The <a href="#KtxInfo">KtxInfo</a> property accessor object.</li>
</ul>
</li>
<li><strong>ktxBundle.info()</strong>
<li><strong>ktx1Bundle.info()</strong>
<ul>
<li>Obtains properties of the KTX header.</li>
<li><em>returns</em> The <a href="#KtxInfo">KtxInfo</a> property accessor object.</li>
</ul>
</li>
<li><strong>ktxBundle.isCompressed()</strong>
<li><strong>ktx1Bundle.isCompressed()</strong>
<ul>
<li><em>returns</em> boolean</li>
</ul>
</li>
</ul>
<p>Most clients should use one of the <code>create*FromKtx</code> utility methods in the JavaScript <a href="#Engine">Engine</a>
wrapper rather than interacting with <code>KtxBundle</code> directly.</p>
wrapper rather than interacting with <code>Ktx1Bundle</code> directly.</p>
</div>
<div class='classdoc'>
<h2>class <a id='KtxInfo' href='#KtxInfo'>KtxInfo</a></h2>
@@ -743,7 +748,7 @@ wrapper rather than interacting with <code>KtxBundle</code> directly.</p>
</ul>
</li>
</ul>
<p>For example, <code>ktxbundle.info().pixelWidth</code>. See the
<p>For example, <code>Ktx1Bundle.info().pixelWidth</code>. See the
<a href="https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/">KTX spec</a> for the list of
properties.</p>
</div>
@@ -1267,7 +1272,9 @@ This defines the following functions:</p>
<ul>
<li>POINTS</li>
<li>LINES</li>
<li>LINE_STRIP</li>
<li>TRIANGLES</li>
<li>TRIANGLE_STRIP</li>
<li>NONE</li>
</ul>
</div>
@@ -1438,6 +1445,14 @@ This defines the following functions:</p>
<li>CUSTOM5</li>
<li>CUSTOM6</li>
<li>CUSTOM7</li>
<li>MORPH_POSITION_0</li>
<li>MORPH_POSITION_1</li>
<li>MORPH_POSITION_2</li>
<li>MORPH_POSITION_3</li>
<li>MORPH_TANGENTS_0</li>
<li>MORPH_TANGENTS_1</li>
<li>MORPH_TANGENTS_2</li>
<li>MORPH_TANGENTS_3</li>
</ul>
</div>
<div class='enumdoc'>
Binary file not shown.
Binary file not shown.
Binary file not shown.
+18 -16
View File
@@ -12,7 +12,9 @@ textures.</p>
<a href="tutorial_triangle.html">previous tutorial</a>. Change the last script tag from <code>triangle.js</code> to <code>redball.js</code>.</p>
<p>Next you'll need to get a couple command-line tools: <code>matc</code> and <code>cmgen</code>. You can find these in the
appropriate <a href="//github.com/google/filament/releases">Filament release</a>. You should choose the
archive that corresponds to your development machine rather than the one for web.</p>
archive that corresponds to your development machine rather than the one for web, and the version
that matches the <code>unpkg.com/filament@x.x.x</code> url in the script tag of <code>redball.html</code> (you may check
out the last available release of <a href="https://www.npmjs.com/package/filament">filament on npm</a>).</p>
<h2>Define plastic material</h2>
<p>The <code>matc</code> tool consumes a text file containing a high-level description of a PBR material, and
produces a binary material package that contains shader code and associated metadata. For more
@@ -60,12 +62,12 @@ IBL KTX contains these coefficients in its metadata.</p>
<h2>Create JavaScript</h2>
<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> environ <span style="color: #666666">=</span> <span style="color: #BA2121">&#39;pillars_2k&#39;</span>;
<span style="color: #008000; font-weight: bold">const</span> ibl_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">_ibl.ktx`</span>;
<span style="color: #008000; font-weight: bold">const</span> sky_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">_skybox.ktx`</span>;
<span style="color: #008000; font-weight: bold">const</span> ibl_url <span style="color: #666666">=</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> sky_url <span style="color: #666666">=</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> filamat_url <span style="color: #666666">=</span> <span style="color: #BA2121">&#39;plastic.filamat&#39;</span>
Filament.init([ filamat_url, ibl_url, sky_url ], () =&gt; {
<span style="color: #408080; font-style: italic">// Create some global aliases to enums for convenience.</span>
<span style="color: #3D7B7B; font-style: italic">// Create some global aliases to enums for convenience.</span>
<span style="color: #008000">window</span>.VertexAttribute <span style="color: #666666">=</span> Filament.VertexAttribute;
<span style="color: #008000">window</span>.AttributeType <span style="color: #666666">=</span> Filament.VertexBuffer$AttributeType;
<span style="color: #008000">window</span>.PrimitiveType <span style="color: #666666">=</span> Filament.RenderableManager$PrimitiveType;
@@ -73,7 +75,7 @@ Filament.init([ filamat_url, ibl_url, sky_url ], () =&gt; {
<span style="color: #008000">window</span>.Fov <span style="color: #666666">=</span> Filament.Camera$Fov;
<span style="color: #008000">window</span>.LightType <span style="color: #666666">=</span> Filament.LightManager$Type;
<span style="color: #408080; font-style: italic">// Obtain the canvas DOM object and pass it to the App.</span>
<span style="color: #3D7B7B; font-style: italic">// Obtain the canvas DOM object and pass it to the App.</span>
<span style="color: #008000; font-weight: bold">const</span> canvas <span style="color: #666666">=</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: #008000">window</span>.app <span style="color: #666666">=</span> <span style="color: #AA22FF; font-weight: bold">new</span> App(canvas);
} );
@@ -84,11 +86,11 @@ Filament.init([ filamat_url, ibl_url, sky_url ], () =&gt; {
<span style="color: #008000; font-weight: bold">const</span> engine <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine <span style="color: #666666">=</span> Filament.Engine.create(canvas);
<span style="color: #008000; font-weight: bold">const</span> scene <span style="color: #666666">=</span> engine.createScene();
<span style="color: #408080; font-style: italic">// TODO: create material</span>
<span style="color: #408080; font-style: italic">// TODO: create sphere</span>
<span style="color: #408080; font-style: italic">// TODO: create lights</span>
<span style="color: #408080; font-style: italic">// TODO: create IBL</span>
<span style="color: #408080; font-style: italic">// TODO: create skybox</span>
<span style="color: #3D7B7B; font-style: italic">// TODO: create material</span>
<span style="color: #3D7B7B; font-style: italic">// TODO: create sphere</span>
<span style="color: #3D7B7B; font-style: italic">// TODO: create lights</span>
<span style="color: #3D7B7B; font-style: italic">// TODO: create IBL</span>
<span style="color: #3D7B7B; font-style: italic">// TODO: create skybox</span>
<span style="color: #008000; font-weight: bold">this</span>.swapChain <span style="color: #666666">=</span> engine.createSwapChain();
<span style="color: #008000; font-weight: bold">this</span>.renderer <span style="color: #666666">=</span> engine.createRenderer();
@@ -209,9 +211,9 @@ following (don't type this out, there'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> format <span style="color: #666666">=</span> Filament.PixelDataFormat.RGB;
<span style="color: #008000; font-weight: bold">const</span> datatype <span style="color: #666666">=</span> Filament.PixelDataType.UINT_10F_11F_11F_REV;
<span style="color: #408080; 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: #008000; font-weight: bold">const</span> ibl_package <span style="color: #666666">=</span> Filament.Buffer(Filament.assets[ibl_url]);
<span style="color: #008000; font-weight: bold">const</span> iblktx <span style="color: #666666">=</span> <span style="color: #AA22FF; font-weight: bold">new</span> Filament.KtxBundle(ibl_package);
<span style="color: #008000; font-weight: bold">const</span> iblktx <span style="color: #666666">=</span> <span style="color: #AA22FF; font-weight: bold">new</span> Filament.Ktx1Bundle(ibl_package);
<span style="color: #008000; font-weight: bold">const</span> ibltex <span style="color: #666666">=</span> Filament.Texture.Builder()
.width(iblktx.info().pixelWidth)
@@ -227,11 +229,11 @@ following (don't type this out, there's an easier way).</p>
ibltex.setImageCube(engine, level, pixelbuffer);
}
<span style="color: #408080; 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: #008000; font-weight: bold">const</span> shstring <span style="color: #666666">=</span> iblktx.getMetadata(<span style="color: #BA2121">&#39;sh&#39;</span>);
<span style="color: #008000; font-weight: bold">const</span> shfloats <span style="color: #666666">=</span> shstring.split(<span style="color: #BB6688">/\s/</span>, <span style="color: #666666">9</span> <span style="color: #666666">*</span> <span style="color: #666666">3</span>).map(<span style="color: #008000">parseFloat</span>);
<span style="color: #008000; font-weight: bold">const</span> shfloats <span style="color: #666666">=</span> shstring.split(<span style="color: #A45A77">/\s/</span>, <span style="color: #666666">9</span> <span style="color: #666666">*</span> <span style="color: #666666">3</span>).map(<span style="color: #008000">parseFloat</span>);
<span style="color: #408080; 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: #008000; font-weight: bold">const</span> indirectLight <span style="color: #666666">=</span> Filament.IndirectLight.Builder()
.reflections(ibltex)
.irradianceSh(<span style="color: #666666">3</span>, shfloats)
@@ -253,7 +255,7 @@ scene.setIndirectLight(indirectLight);
Without a skybox, the reflections on the ball are not representative of its surroundings.
Here'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> sky_package <span style="color: #666666">=</span> Filament.Buffer(Filament.assets[sky_url]);
<span style="color: #008000; font-weight: bold">const</span> skyktx <span style="color: #666666">=</span> <span style="color: #AA22FF; font-weight: bold">new</span> Filament.KtxBundle(sky_package);
<span style="color: #008000; font-weight: bold">const</span> skyktx <span style="color: #666666">=</span> <span style="color: #AA22FF; font-weight: bold">new</span> Filament.Ktx1Bundle(sky_package);
<span style="color: #008000; font-weight: bold">const</span> skytex <span style="color: #666666">=</span> Filament.Texture.Builder()
.width(skyktx.info().pixelWidth)
.height(skyktx.info().pixelHeight)
+21 -21
View File
@@ -22,25 +22,25 @@ converting <a href="https://github.com/google/filament/blob/main/assets/models/m
<p>Next, let's create mipmapped KTX files using filament's <code>mipgen</code> tool. We'll create compressed and
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>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #408080; 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 albedo.png albedo.ktx
mipgen --compression<span style="color: #666666">=</span>astc_fast_ldr_4x4 albedo.png albedo_astc.ktx
mipgen --compression<span style="color: #666666">=</span>s3tc_rgb_dxt1 albedo.png albedo_s3tc_srgb.ktx
<span style="color: #408080; 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 --strip-alpha --kernel<span style="color: #666666">=</span>NORMALS --linear normal.png normal.ktx
mipgen --strip-alpha --kernel<span style="color: #666666">=</span>NORMALS --linear --compression<span style="color: #666666">=</span>etc_rgb8_normalxyz_40 <span style="color: #BB6622; 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>
normal.png normal_etc.ktx
<span style="color: #408080; 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 --grayscale roughness.png roughness.ktx
mipgen --grayscale --compression<span style="color: #666666">=</span>etc_r11_numeric_40 roughness.png roughness_etc.ktx
<span style="color: #408080; 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 --grayscale metallic.png metallic.ktx
mipgen --grayscale --compression<span style="color: #666666">=</span>etc_r11_numeric_40 metallic.png metallic_etc.ktx
<span style="color: #408080; 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 --grayscale ao.png ao.ktx
mipgen --grayscale --compression<span style="color: #666666">=</span>etc_r11_numeric_40 ao.png ao_etc.ktx
</pre></div>
@@ -101,7 +101,7 @@ 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
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>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #408080; 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>
Filament.init([ filamat_url, filamesh_url, sky_small_url, ibl_url ], () =&gt; {
<span style="color: #008000">window</span>.app <span style="color: #666666">=</span> <span style="color: #AA22FF; font-weight: bold">new</span> App(<span style="color: #008000">document</span>.getElementsByTagName(<span style="color: #BA2121">&#39;canvas&#39;</span>)[<span style="color: #666666">0</span>]);
@@ -119,9 +119,9 @@ Filament.init([ filamat_url, filamesh_url, sky_small_url, ibl_url ], () =&gt; {
<span style="color: #008000; font-weight: bold">const</span> filamesh <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.loadFilamesh(filamesh_url, <span style="color: #008000; font-weight: bold">this</span>.matinstance);
<span style="color: #008000; font-weight: bold">this</span>.suzanne <span style="color: #666666">=</span> filamesh.renderable;
<span style="color: #408080; font-style: italic">// TODO: create sky box and IBL</span>
<span style="color: #408080; font-style: italic">// TODO: initialize gltumble</span>
<span style="color: #408080; font-style: italic">// TODO: fetch larger assets</span>
<span style="color: #3D7B7B; font-style: italic">// TODO: create sky box and IBL</span>
<span style="color: #3D7B7B; font-style: italic">// TODO: initialize gltumble</span>
<span style="color: #3D7B7B; font-style: italic">// TODO: fetch larger assets</span>
<span style="color: #008000; font-weight: bold">this</span>.swapChain <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createSwapChain();
<span style="color: #008000; font-weight: bold">this</span>.renderer <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createRenderer();
@@ -141,7 +141,7 @@ Filament.init([ filamat_url, filamesh_url, sky_small_url, ibl_url ], () =&gt; {
}
render() {
<span style="color: #408080; font-style: italic">// TODO: apply gltumble matrix</span>
<span style="color: #3D7B7B; font-style: italic">// TODO: apply gltumble matrix</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: #008000; font-weight: bold">this</span>.view);
<span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);
}
@@ -176,14 +176,14 @@ last resort. Go ahead and replace the <strong>declare asset URLs</strong> commen
<span style="color: #008000; font-weight: bold">const</span> texture_suffix <span style="color: #666666">=</span> Filament.getSupportedFormatSuffix(<span style="color: #BA2121">&#39;etc&#39;</span>);
<span style="color: #008000; font-weight: bold">const</span> environ <span style="color: #666666">=</span> <span style="color: #BA2121">&#39;venetian_crossroads_2k&#39;</span>
<span style="color: #008000; font-weight: bold">const</span> ibl_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">_ibl.ktx`</span>;
<span style="color: #008000; font-weight: bold">const</span> sky_small_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">_skybox_tiny.ktx`</span>;
<span style="color: #008000; font-weight: bold">const</span> sky_large_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">_skybox.ktx`</span>;
<span style="color: #008000; font-weight: bold">const</span> albedo_url <span style="color: #666666">=</span> <span style="color: #BA2121">`albedo</span><span style="color: #BB6688; font-weight: bold">${</span>albedo_suffix<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
<span style="color: #008000; font-weight: bold">const</span> ao_url <span style="color: #666666">=</span> <span style="color: #BA2121">`ao</span><span style="color: #BB6688; font-weight: bold">${</span>texture_suffix<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
<span style="color: #008000; font-weight: bold">const</span> metallic_url <span style="color: #666666">=</span> <span style="color: #BA2121">`metallic</span><span style="color: #BB6688; font-weight: bold">${</span>texture_suffix<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
<span style="color: #008000; font-weight: bold">const</span> normal_url <span style="color: #666666">=</span> <span style="color: #BA2121">`normal</span><span style="color: #BB6688; font-weight: bold">${</span>texture_suffix<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
<span style="color: #008000; font-weight: bold">const</span> roughness_url <span style="color: #666666">=</span> <span style="color: #BA2121">`roughness</span><span style="color: #BB6688; font-weight: bold">${</span>texture_suffix<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
<span style="color: #008000; font-weight: bold">const</span> ibl_url <span style="color: #666666">=</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> sky_small_url <span style="color: #666666">=</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> sky_large_url <span style="color: #666666">=</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> albedo_url <span style="color: #666666">=</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> ao_url <span style="color: #666666">=</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> metallic_url <span style="color: #666666">=</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> normal_url <span style="color: #666666">=</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> roughness_url <span style="color: #666666">=</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> filamat_url <span style="color: #666666">=</span> <span style="color: #BA2121">&#39;textured.filamat&#39;</span>;
<span style="color: #008000; font-weight: bold">const</span> filamesh_url <span style="color: #666666">=</span> <span style="color: #BA2121">&#39;suzanne.filamesh&#39;</span>;
</pre></div>
@@ -224,7 +224,7 @@ was created in the app constructor.</p>
<span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">&#39;normal&#39;</span>, normal, sampler);
<span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">&#39;ao&#39;</span>, ao, sampler);
<span style="color: #408080; font-style: italic">// Replace low-res skybox with high-res skybox.</span>
<span style="color: #3D7B7B; font-style: italic">// Replace low-res skybox with high-res skybox.</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: #008000; font-weight: bold">this</span>.skybox <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createSkyFromKtx(sky_large_url);
<span style="color: #008000; font-weight: bold">this</span>.scene.setSkybox(<span style="color: #008000; font-weight: bold">this</span>.skybox);
@@ -236,7 +236,7 @@ was created in the app constructor.</p>
<h2>Introduce trackball rotation</h2>
<p>Add the following script tag to your HTML file. This imports a small third-party library that
listens for drag events and computes a rotation matrix.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>&lt;<span style="color: #008000; font-weight: bold">script</span> <span style="color: #7D9029">src</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;//unpkg.com/gltumble&quot;</span>&gt;&lt;/<span style="color: #008000; font-weight: bold">script</span>&gt;
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>&lt;<span style="color: #008000; font-weight: bold">script</span> <span style="color: #687822">src</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;//unpkg.com/gltumble&quot;</span>&gt;&lt;/<span style="color: #008000; font-weight: bold">script</span>&gt;
</pre></div>
<p>Next, replace the <strong>initialize gltumble</strong> and <strong>apply gltumble matrix</strong> comments with the following
+22 -22
View File
@@ -16,22 +16,22 @@ subsequent code blocks.</p>
<h2>Start your project</h2>
<p>First, create a text file called <code>triangle.html</code> and fill it with the following HTML. This creates
a mobile-friendly page with a full-screen canvas.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #BC7A00">&lt;!DOCTYPE html&gt;</span>
&lt;<span style="color: #008000; font-weight: bold">html</span> <span style="color: #7D9029">lang</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;en&quot;</span>&gt;
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #9C6500">&lt;!DOCTYPE html&gt;</span>
&lt;<span style="color: #008000; font-weight: bold">html</span> <span style="color: #687822">lang</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;en&quot;</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">head</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: #7D9029">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: #7D9029">name</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;viewport&quot;</span> <span style="color: #7D9029">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;
<span style="color: #008000; font-weight: bold">body</span> { <span style="color: #008000; font-weight: bold">margin</span>: <span style="color: #666666">0</span>; <span style="color: #008000; font-weight: bold">overflow</span>: <span style="color: #008000; font-weight: bold">hidden</span>; }
<span style="color: #008000; font-weight: bold">canvas</span> { touch-action: <span style="color: #008000; font-weight: bold">none</span>; <span style="color: #008000; font-weight: bold">width</span>: <span style="color: #666666">100</span><span style="color: #B00040">%</span>; <span style="color: #008000; font-weight: bold">height</span>: <span style="color: #666666">100</span><span style="color: #B00040">%</span>; }
&lt;/<span style="color: #008000; font-weight: bold">style</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">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: #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;
&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">canvas</span>&gt;&lt;/<span style="color: #008000; font-weight: bold">canvas</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">script</span> <span style="color: #7D9029">src</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;//unpkg.com/filament@1.15.0/filament.js&quot;</span>&gt;&lt;/<span style="color: #008000; font-weight: bold">script</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">script</span> <span style="color: #7D9029">src</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;//unpkg.com/gl-matrix@2.8.1&quot;</span>&gt;&lt;/<span style="color: #008000; font-weight: bold">script</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">script</span> <span style="color: #7D9029">src</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;triangle.js&quot;</span>&gt;&lt;/<span style="color: #008000; font-weight: bold">script</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">script</span> <span style="color: #687822">src</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;filament.js&quot;</span>&gt;&lt;/<span style="color: #008000; font-weight: bold">script</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">script</span> <span style="color: #687822">src</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;//unpkg.com/gl-matrix@2.8.1&quot;</span>&gt;&lt;/<span style="color: #008000; font-weight: bold">script</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">script</span> <span style="color: #687822">src</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;triangle.js&quot;</span>&gt;&lt;/<span style="color: #008000; font-weight: bold">script</span>&gt;
&lt;/<span style="color: #008000; font-weight: bold">body</span>&gt;
&lt;/<span style="color: #008000; font-weight: bold">html</span>&gt;
</pre></div>
@@ -50,18 +50,18 @@ a mobile-friendly page with a full-screen canvas.</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> App {
<span style="color: #008000; font-weight: bold">constructor</span>() {
<span style="color: #408080; font-style: italic">// TODO: create entities</span>
<span style="color: #3D7B7B; font-style: italic">// TODO: create entities</span>
<span style="color: #008000; font-weight: bold">this</span>.render <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.render.bind(<span style="color: #008000; font-weight: bold">this</span>);
<span style="color: #008000; font-weight: bold">this</span>.resize <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.resize.bind(<span style="color: #008000; font-weight: bold">this</span>);
<span style="color: #008000">window</span>.addEventListener(<span style="color: #BA2121">&#39;resize&#39;</span>, <span style="color: #008000; font-weight: bold">this</span>.resize);
<span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);
}
render() {
<span style="color: #408080; font-style: italic">// TODO: render scene</span>
<span style="color: #3D7B7B; font-style: italic">// TODO: render scene</span>
<span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);
}
resize() {
<span style="color: #408080; font-style: italic">// TODO: adjust viewport and canvas</span>
<span style="color: #3D7B7B; font-style: italic">// TODO: adjust viewport and canvas</span>
}
}
@@ -81,9 +81,9 @@ that define a PBR material. We'll learn more about material packages in the next
<h2>Spawn a local server</h2>
<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>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>python3 -m http.server <span style="color: #408080; font-style: italic"># Python 3</span>
python -m SimpleHTTPServer <span style="color: #408080; font-style: italic"># Python 2.7</span>
npx http-server -p <span style="color: #666666">8000</span> <span style="color: #408080; font-style: italic"># nodejs</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 -m SimpleHTTPServer <span style="color: #3D7B7B; font-style: italic"># Python 2.7</span>
npx http-server -p <span style="color: #666666">8000</span> <span style="color: #3D7B7B; font-style: italic"># nodejs</span>
</pre></div>
<p>To see if this works, navigate to <a href="http://localhost:8000">http://localhost:8000</a> and check if you
@@ -185,10 +185,10 @@ view.</p>
<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.setScene(<span style="color: #008000; font-weight: bold">this</span>.scene);
<span style="color: #408080; 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: #008000; font-weight: bold">this</span>.renderer.setClearOptions({clearColor<span style="color: #666666">:</span> [<span style="color: #666666">0.0</span>, <span style="color: #666666">0.1</span>, <span style="color: #666666">0.2</span>, <span style="color: #666666">1.0</span>], clear<span style="color: #666666">:</span> <span style="color: #008000; font-weight: bold">true</span>});
<span style="color: #408080; font-style: italic">// Adjust the initial viewport:</span>
<span style="color: #3D7B7B; font-style: italic">// Adjust the initial viewport:</span>
<span style="color: #008000; font-weight: bold">this</span>.resize();
</pre></div>
@@ -198,14 +198,14 @@ However the canvas is still blank!</p>
<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>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>render() {
<span style="color: #408080; font-style: italic">// TODO: render scene</span>
<span style="color: #3D7B7B; font-style: italic">// TODO: render scene</span>
<span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);
}
</pre></div>
<p>Let'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>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #408080; 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: #008000; font-weight: bold">const</span> radians <span style="color: #666666">=</span> <span style="color: #008000">Date</span>.now() <span style="color: #666666">/</span> <span style="color: #666666">1000</span>;
<span style="color: #008000; font-weight: bold">const</span> transform <span style="color: #666666">=</span> mat4.fromRotation(mat4.create(), radians, [<span style="color: #666666">0</span>, <span style="color: #666666">0</span>, <span style="color: #666666">1</span>]);
<span style="color: #008000; font-weight: bold">const</span> tcm <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.getTransformManager();
@@ -213,7 +213,7 @@ code to the top of the render method.</p>
tcm.setTransform(inst, transform);
inst.<span style="color: #AA22FF; font-weight: bold">delete</span>();
<span style="color: #408080; font-style: italic">// Render the frame.</span>
<span style="color: #3D7B7B; font-style: italic">// Render the frame.</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: #008000; font-weight: bold">this</span>.view);
</pre></div>
+53 -24
View File
@@ -52,7 +52,6 @@ set(SRCS
src/BufferObject.cpp
src/Camera.cpp
src/Color.cpp
src/ColorGrading.cpp
src/ColorSpace.cpp
src/Culler.cpp
src/DFG.cpp
@@ -64,9 +63,9 @@ set(SRCS
src/FrameSkipper.cpp
src/Froxelizer.cpp
src/Frustum.cpp
src/fsr.cpp
src/IndexBuffer.cpp
src/IndirectLight.cpp
src/LightManager.cpp
src/Material.cpp
src/MaterialInstance.cpp
src/MaterialParser.cpp
@@ -76,8 +75,11 @@ set(SRCS
src/RenderPass.cpp
src/RenderPrimitive.cpp
src/RenderTarget.cpp
src/RenderableManager.cpp
src/Renderer.cpp
src/RendererUtils.cpp
src/ResourceAllocator.cpp
src/ResourceList.cpp
src/Scene.cpp
src/ShadowMap.cpp
src/ShadowMapManager.cpp
@@ -87,22 +89,44 @@ set(SRCS
src/SwapChain.cpp
src/Texture.cpp
src/ToneMapper.cpp
src/TransformManager.cpp
src/UniformBuffer.cpp
src/VertexBuffer.cpp
src/View.cpp
src/Viewport.cpp
src/components/CameraManager.cpp
src/components/LightManager.cpp
src/components/RenderableManager.cpp
src/components/TransformManager.cpp
src/fg2/Blackboard.cpp
src/fg2/DependencyGraph.cpp
src/fg2/FrameGraph.cpp
src/fg2/FrameGraphPass.cpp
src/fg2/FrameGraphResources.cpp
src/fg2/FrameGraphTexture.cpp
src/fg2/PassNode.cpp
src/fg2/ResourceNode.cpp
src/details/BufferObject.cpp
src/details/Camera.cpp
src/details/ColorGrading.cpp
src/details/DebugRegistry.cpp
src/details/Engine.cpp
src/details/Fence.cpp
src/details/IndexBuffer.cpp
src/details/IndirectLight.cpp
src/details/Material.cpp
src/details/MaterialInstance.cpp
src/details/MorphTargetBuffer.cpp
src/details/RenderTarget.cpp
src/details/Renderer.cpp
src/details/Scene.cpp
src/details/SkinningBuffer.cpp
src/details/Skybox.cpp
src/details/Stream.cpp
src/details/SwapChain.cpp
src/details/Texture.cpp
src/details/VertexBuffer.cpp
src/details/View.cpp
src/fg/Blackboard.cpp
src/fg/DependencyGraph.cpp
src/fg/FrameGraph.cpp
src/fg/FrameGraphPass.cpp
src/fg/FrameGraphResources.cpp
src/fg/FrameGraphTexture.cpp
src/fg/PassNode.cpp
src/fg/ResourceNode.cpp
src/fsr.cpp
)
set(PRIVATE_HDRS
@@ -120,6 +144,7 @@ set(PRIVATE_HDRS
src/PerViewUniforms.h
src/PIDController.h
src/PostProcessManager.h
src/RendererUtils.h
src/RenderPass.h
src/RenderPrimitive.h
src/ResourceAllocator.h
@@ -153,19 +178,19 @@ set(PRIVATE_HDRS
src/details/Texture.h
src/details/VertexBuffer.h
src/details/View.h
src/fg2/Blackboard.h
src/fg2/FrameGraph.h
src/fg2/FrameGraphId.h
src/fg2/FrameGraphPass.h
src/fg2/FrameGraphRenderPass.h
src/fg2/FrameGraphResources.h
src/fg2/FrameGraphTexture.h
src/fg2/Resource.cpp
src/fg2/details/DependencyGraph.h
src/fg2/details/PassNode.h
src/fg2/details/Resource.h
src/fg2/details/ResourceNode.h
src/fg2/details/Utilities.h
src/fg/Blackboard.h
src/fg/FrameGraph.h
src/fg/FrameGraphId.h
src/fg/FrameGraphPass.h
src/fg/FrameGraphRenderPass.h
src/fg/FrameGraphResources.h
src/fg/FrameGraphTexture.h
src/fg/Resource.cpp
src/fg/details/DependencyGraph.h
src/fg/details/PassNode.h
src/fg/details/Resource.h
src/fg/details/ResourceNode.h
src/fg/details/Utilities.h
src/fsr.h
src/materials/fsr/ffx_a.h
src/materials/fsr/ffx_fsr1.h
@@ -205,6 +230,10 @@ set(MATERIAL_SRCS
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/taa.mat
src/materials/vsmMipmap.mat
+3 -7
View File
@@ -42,6 +42,7 @@ set(PRIVATE_HDRS
include/private/backend/CircularBuffer.h
include/private/backend/CommandBufferQueue.h
include/private/backend/CommandStream.h
include/private/backend/Dispatcher.h
include/private/backend/Driver.h
include/private/backend/DriverApi.h
include/private/backend/DriverAPI.inc
@@ -64,8 +65,6 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMEN
src/opengl/gl_headers.h
src/opengl/GLUtils.cpp
src/opengl/GLUtils.h
src/opengl/OpenGLBlitter.cpp
src/opengl/OpenGLBlitter.h
src/opengl/OpenGLContext.cpp
src/opengl/OpenGLContext.h
src/opengl/OpenGLDriver.cpp
@@ -74,8 +73,8 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMEN
src/opengl/OpenGLProgram.cpp
src/opengl/OpenGLProgram.h
src/opengl/OpenGLPlatform.cpp
src/opengl/TimerQuery.cpp
src/opengl/TimerQuery.h
src/opengl/OpenGLTimerQuery.cpp
src/opengl/OpenGLTimerQuery.h
include/private/backend/OpenGLPlatform.h
)
if (EGL)
@@ -88,7 +87,6 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMEN
endif ()
if (ANDROID)
list(APPEND SRCS src/opengl/platforms/ExternalStreamManagerAndroid.cpp)
list(APPEND SRCS src/android/ExternalTextureManagerAndroid.cpp)
list(APPEND SRCS src/opengl/platforms/PlatformEGLAndroid.cpp)
elseif (IOS)
list(APPEND SRCS src/opengl/platforms/PlatformCocoaTouchGL.mm)
@@ -395,7 +393,6 @@ if (APPLE)
target_link_libraries(backend_test PRIVATE
backend
filabridge
getopt
gtest
SPIRV
@@ -408,7 +405,6 @@ if (APPLE)
SPIRV-Tools
SPIRV-Tools-opt
backend_test
filabridge
getopt
gtest
glslang
+48 -20
View File
@@ -33,7 +33,6 @@
#include <stddef.h>
#include <stdint.h>
namespace filament {
/**
* Types and enums used by filament's driver.
*
@@ -41,22 +40,24 @@ namespace filament {
* internal redeclaration of these types.
* For e.g. Use Texture::Sampler instead of filament::SamplerType.
*/
namespace backend {
namespace filament::backend {
static constexpr uint64_t SWAP_CHAIN_CONFIG_TRANSPARENT = 0x1;
static constexpr uint64_t SWAP_CHAIN_CONFIG_READABLE = 0x2;
static constexpr uint64_t SWAP_CHAIN_CONFIG_ENABLE_XCB = 0x4;
static constexpr uint64_t SWAP_CHAIN_CONFIG_TRANSPARENT = 0x1;
static constexpr uint64_t SWAP_CHAIN_CONFIG_READABLE = 0x2;
static constexpr uint64_t SWAP_CHAIN_CONFIG_ENABLE_XCB = 0x4;
static constexpr uint64_t SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER = 0x8;
static constexpr size_t MAX_VERTEX_ATTRIBUTE_COUNT = 16; // This is guaranteed by OpenGL ES.
static constexpr size_t MAX_SAMPLER_COUNT = 16; // Matches the Adreno Vulkan driver.
static constexpr size_t MAX_VERTEX_BUFFER_COUNT = 16; // Max number of bound buffer objects.
static constexpr size_t MAX_VERTEX_ATTRIBUTE_COUNT = 16; // This is guaranteed by OpenGL ES.
static constexpr size_t MAX_VERTEX_SAMPLER_COUNT = 16; // This is guaranteed by OpenGL ES.
static constexpr size_t MAX_FRAGMENT_SAMPLER_COUNT = 16; // This is guaranteed by OpenGL ES.
static constexpr size_t MAX_SAMPLER_COUNT = 32; // This is guaranteed by OpenGL ES.
static constexpr size_t MAX_VERTEX_BUFFER_COUNT = 16; // Max number of bound buffer objects.
static_assert(MAX_VERTEX_BUFFER_COUNT <= MAX_VERTEX_ATTRIBUTE_COUNT,
"The number of buffer objects that can be attached to a VertexBuffer must be "
"less than or equal to the maximum number of vertex attributes.");
static constexpr size_t CONFIG_BINDING_COUNT = 8;
static constexpr size_t CONFIG_BINDING_COUNT = 12; // This is guaranteed by OpenGL ES.
/**
* Selects which driver a particular Engine should use.
@@ -140,9 +141,9 @@ struct Viewport {
uint32_t width; //!< width in pixels
uint32_t height; //!< height in pixels
//! get the right coordinate in window space of the viewport
int32_t right() const noexcept { return left + width; }
int32_t right() const noexcept { return left + int32_t(width); }
//! get the top coordinate in window space of the viewport
int32_t top() const noexcept { return bottom + height; }
int32_t top() const noexcept { return bottom + int32_t(height); }
};
/**
@@ -158,7 +159,7 @@ struct DepthRange {
* @see Fence, Fence::wait()
*/
enum class FenceStatus : int8_t {
ERROR = -1, //!< An error occured. The Fence condition is not satisfied.
ERROR = -1, //!< An error occurred. The Fence condition is not satisfied.
CONDITION_SATISFIED = 0, //!< The Fence condition is satisfied.
TIMEOUT_EXPIRED = 1, //!< wait()'s timeout expired. The Fence condition is not satisfied.
};
@@ -167,7 +168,7 @@ enum class FenceStatus : int8_t {
* Status codes for sync objects
*/
enum class SyncStatus : int8_t {
ERROR = -1, //!< An error occured. The Sync is not signaled.
ERROR = -1, //!< An error occurred. The Sync is not signaled.
SIGNALED = 0, //!< The Sync is signaled.
NOT_SIGNALED = 1, //!< The Sync is not signaled yet
};
@@ -638,6 +639,10 @@ enum class TextureCubemapFace : uint8_t {
NEGATIVE_Z = 5, //!< -z face
};
inline constexpr int operator +(TextureCubemapFace rhs) noexcept {
return int(rhs);
}
//! Face offsets for all faces of a cubemap
struct FaceOffsets {
using size_type = size_t;
@@ -783,7 +788,6 @@ enum class BlendFunction : uint8_t {
//! Stream for external textures
enum class StreamType {
NATIVE, //!< Not synchronized but copy-free. Good for video.
TEXTURE_ID, //!< Synchronized, but GL-only and incurs copies. Good for AR on devices before API 26.
ACQUIRED, //!< Synchronized, copy-free, and take a release callback. Good for AR but requires API 26+.
};
@@ -900,6 +904,16 @@ enum ShaderType : uint8_t {
};
static constexpr size_t PIPELINE_STAGE_COUNT = 2;
struct ShaderStageFlags {
bool vertex : 1;
bool fragment : 1;
bool hasShaderType(ShaderType type) const {
return (vertex && type == ShaderType::VERTEX) ||
(fragment && type == ShaderType::FRAGMENT);
}
};
static constexpr ShaderStageFlags ALL_SHADER_STAGE_FLAGS = { true, true };
/**
* Selects which buffers to clear at the beginning of the render pass, as well as which buffers
* can be discarded at the beginning and end of the render pass.
@@ -948,10 +962,20 @@ struct RenderPassParams {
* subpass. If this is zero, the render pass has only one subpass. The least significant bit
* specifies that the first color attachment in the render target is a subpass input.
*
* For now only 2 subpasses are supported, so only the lower 4 bits are used, one for each color
* attachment (see MRT::TARGET_COUNT).
* For now only 2 subpasses are supported, so only the lower 8 bits are used, one for each color
* attachment (see MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT).
*/
uint32_t subpassMask = 0;
uint16_t subpassMask = 0;
/**
* This mask makes a promise to the backend about read-only usage of the depth attachment (bit
* 0) and the stencil attachment (bit 1). Some backends need to know if writes are disabled in
* order to allow sampling from the depth attachment.
*/
uint16_t readOnlyDepthStencil = 0;
static constexpr uint16_t READONLY_DEPTH = 1 << 0;
static constexpr uint16_t READONLY_STENCIL = 1 << 1;
};
struct PolygonOffset {
@@ -965,11 +989,14 @@ using FrameScheduledCallback = void(*)(PresentCallable callable, void* user);
using FrameCompletedCallback = void(*)(void* user);
enum class Workaround : uint16_t {
SPLIT_EASU
// The EASU pass must split because shader compiler flattens early-exit branch
SPLIT_EASU,
// Backend allows feedback loop with ancillary buffers (depth/stencil) as long as they're read-only for
// the whole render pass.
ALLOW_READ_ONLY_ANCILLARY_FEEDBACK_LOOP
};
} // namespace backend
} // namespace filament
} // namespace filament::backend
template<> struct utils::EnableBitMaskOperators<filament::backend::TargetBufferFlags>
: public std::true_type {};
@@ -1006,6 +1033,7 @@ utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend:
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::RasterState& rs);
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::RenderPassParams& b);
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::Viewport& v);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::ShaderStageFlags stageFlags);
#endif
#endif // TNT_FILAMENT_BACKEND_DRIVERENUMS_H
+40 -23
View File
@@ -18,13 +18,16 @@
#define TNT_FILAMENT_BACKEND_HANDLE_H
#include <utils/compiler.h>
#if !defined(NDEBUG)
#include <utils/Log.h>
#endif
#include <utils/debug.h>
#include <stdint.h>
#include <limits>
namespace filament {
namespace backend {
namespace filament::backend {
struct HwBufferObject;
struct HwFence;
@@ -41,7 +44,9 @@ struct HwTimerQuery;
struct HwVertexBuffer;
/*
* A type handle to a h/w resource
* A handle to a backend resource. HandleBase is for internal use only.
* HandleBase *must* be a trivial for the purposes of calls, that is, it cannot have user-defined
* copy or move constructors.
*/
//! \privatesection
@@ -53,41 +58,54 @@ public:
constexpr HandleBase() noexcept: object(nullid) {}
explicit HandleBase(HandleId id) noexcept : object(id) {
assert_invariant(object != nullid); // usually means an uninitialized handle is used
}
HandleBase(HandleBase const& rhs) noexcept = default;
HandleBase(HandleBase&& rhs) noexcept : object(rhs.object) {
rhs.object = nullid;
}
HandleBase& operator=(HandleBase const& rhs) noexcept = default;
HandleBase& operator=(HandleBase&& rhs) noexcept {
std::swap(object, rhs.object);
return *this;
}
// whether this Handle is initialized
explicit operator bool() const noexcept { return object != nullid; }
// clear the handle, this doesn't free associated resources
void clear() noexcept { object = nullid; }
// compare handles
bool operator==(const HandleBase& rhs) const noexcept { return object == rhs.object; }
bool operator!=(const HandleBase& rhs) const noexcept { return object != rhs.object; }
bool operator<(const HandleBase& rhs) const noexcept { return object < rhs.object; }
bool operator<=(const HandleBase& rhs) const noexcept { return object <= rhs.object; }
bool operator>(const HandleBase& rhs) const noexcept { return object > rhs.object; }
bool operator>=(const HandleBase& rhs) const noexcept { return object >= rhs.object; }
// get this handle's handleId
HandleId getId() const noexcept { return object; }
// initialize a handle, for internal use only.
explicit HandleBase(HandleId id) noexcept : object(id) {
assert_invariant(object != nullid); // usually means an uninitialized handle is used
}
protected:
HandleBase(HandleBase const& rhs) noexcept = default;
HandleBase& operator=(HandleBase const& rhs) noexcept = default;
private:
HandleId object;
};
template <typename T>
/**
* Type-safe handle to backend resources
* @tparam T Type of the resource
*/
template<typename T>
struct Handle : public HandleBase {
using HandleBase::HandleBase;
Handle() noexcept = default;
Handle(Handle const& rhs) noexcept = default;
Handle& operator=(Handle const& rhs) noexcept = default;
explicit Handle(HandleId id) noexcept : HandleBase(id) { }
// type-safe Handle cast
template<typename B, typename = std::enable_if_t<std::is_base_of<T, B>::value> >
Handle(Handle<B> const& base) noexcept : HandleBase(base) { } // NOLINT(hicpp-explicit-conversions)
Handle(Handle<B> const& base) noexcept : HandleBase(base) { } // NOLINT(hicpp-explicit-conversions,google-explicit-constructor)
private:
#if !defined(NDEBUG)
@@ -112,7 +130,6 @@ using TextureHandle = Handle<HwTexture>;
using TimerQueryHandle = Handle<HwTimerQuery>;
using VertexBufferHandle = Handle<HwVertexBuffer>;
} // namespace backend
} // namespace filament
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_HANDLE_H
+1 -1
View File
@@ -80,7 +80,7 @@ public:
* underlying platform is returned and \p backendHint is updated
* accordingly. Can't be nullptr.
*
* @return A pointer to the Plaform object.
* @return A pointer to the Platform object.
*
* @see destroy
*/
@@ -22,38 +22,19 @@
#include <stdint.h>
namespace filament {
namespace backend {
namespace filament::backend {
//! \privatesection
class TargetBufferInfo {
public:
// ctor for 2D textures
TargetBufferInfo(Handle<HwTexture> h, uint8_t level = 0) noexcept // NOLINT(google-explicit-constructor)
: handle(h), level(level) { }
// ctor for cubemaps
TargetBufferInfo(Handle<HwTexture> h, uint8_t level, TextureCubemapFace face) noexcept
: handle(h), level(level), face(face) { }
// ctor for 3D textures
TargetBufferInfo(Handle<HwTexture> h, uint8_t level, uint16_t layer) noexcept
: handle(h), level(level), layer(layer) { }
explicit TargetBufferInfo(TextureCubemapFace face) noexcept : face(face) {}
explicit TargetBufferInfo(uint16_t layer) noexcept : layer(layer) {}
struct TargetBufferInfo {
// texture to be used as render target
Handle<HwTexture> handle;
// level to be used
uint8_t level = 0;
union {
// face if texture is a cubemap
TextureCubemapFace face;
// for 3D textures
uint16_t layer = 0;
};
TargetBufferInfo() noexcept { }
// for cubemaps and 3D textures. See TextureCubemapFace for the face->layer mapping
uint16_t layer = 0;
};
class MRT {
@@ -96,13 +77,12 @@ public:
}
// this is here for backward compatibility
MRT(Handle<HwTexture> h, uint8_t level, uint16_t layer) noexcept
: mInfos{{ h, level, layer }} {
MRT(Handle<HwTexture> handle, uint8_t level, uint16_t layer) noexcept
: mInfos{{ handle, level, layer }} {
}
};
} // namespace backend
} // namespace filament
} // namespace filament::backend
#if !defined(NDEBUG)
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::TargetBufferInfo& tbi);
@@ -1,5 +1,3 @@
#include <utility>
/*
* Copyright (C) 2018 The Android Open Source Project
*
@@ -20,64 +18,35 @@
#define TNT_FILAMENT_BACKEND_PRIVATE_COMMANDSTREAM_H
#include "private/backend/CircularBuffer.h"
#include "private/backend/Dispatcher.h"
#include "private/backend/Program.h"
#include "private/backend/SamplerGroup.h"
#include "private/backend/Driver.h"
#include <backend/BufferDescriptor.h>
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
#include <backend/PipelineState.h>
#include <backend/PixelBufferDescriptor.h>
#include <backend/PresentCallable.h>
#include <backend/TargetBufferInfo.h>
#include "private/backend/Program.h"
#include "private/backend/SamplerGroup.h"
// FIXME: we'd like to not need this header here.
#include "private/backend/Driver.h"
#include <backend/DriverEnums.h>
#include <utils/compiler.h>
#include <utils/ThreadUtils.h>
#include <functional>
#include <tuple>
#include <thread>
#include <utility>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
// Set to true to print every commands out on log.d. This requires RTTI and DEBUG
// Set to true to print every command out on log.d. This requires RTTI and DEBUG
#define DEBUG_COMMAND_STREAM false
namespace filament {
namespace backend {
class Driver;
class CommandBase;
/*
* Dispatcher is a data structure containing only function pointers.
* Each function pointer targets code that unpacks the arguments to the driver's method and
* calls it.
*
* Dispatcher's function pointers are populated during initialization and no CommandStream calls
* can be made before that.
*
* When a command is inserted into the stream, the corresponding function pointer is copied
* directly into CommandBase from Dispatcher.
*/
class Dispatcher {
public:
using Execute = void (*)(Driver& driver, CommandBase* self, intptr_t* next);
#define DECL_DRIVER_API_SYNCHRONOUS(RetType, methodName, paramsDecl, params)
#define DECL_DRIVER_API(methodName, paramsDecl, params) Execute methodName##_;
#define DECL_DRIVER_API_RETURN(RetType, methodName, paramsDecl, params) Execute methodName##_;
#include "DriverAPI.inc"
};
// ------------------------------------------------------------------------------------------------
namespace filament::backend {
class CommandBase {
static constexpr size_t FILAMENT_OBJECT_ALIGNMENT = alignof(std::max_align_t);
@@ -95,8 +64,10 @@ public:
// executes this command and returns the next one
inline CommandBase* execute(Driver& driver) {
// it is important to return the next command offset by output parameter instead
// of return value -- it allows the compiler to perform the tail call optimization.
// returning the next command by output parameter allows the compiler to perform the
// tail-call optimization in the function called by mExecute, however that comes at
// a cost here (writing and reading the stack at each iteration), in the end it's
// probably better to pay the cost at just one location.
intptr_t next;
mExecute(driver, this, &next);
return reinterpret_cast<CommandBase*>(reinterpret_cast<intptr_t>(this) + next);
@@ -131,7 +102,7 @@ constexpr decltype(auto) apply(M&& m, D&& d, T&& t) {
/*
* CommandType<> is just a wrapper class to specialize on a pointer-to-member of Driver
* (i.e. a method pointer to a method of Driver of a particular type -- but not the
* method itself). We only do that so we can identify the parameters of that method.
* method itself). We only do that, so we can identify the parameters of that method.
* We won't call through that pointer though.
*/
template<typename... ARGS>
@@ -207,7 +178,7 @@ class NoopCommand : public CommandBase {
}
public:
inline constexpr explicit NoopCommand(void* next) noexcept
: CommandBase(execute), mNext(size_t((char *)next - (char *)this)) { }
: CommandBase(execute), mNext(intptr_t((char *)next - (char *)this)) { }
};
// ------------------------------------------------------------------------------------------------
@@ -215,41 +186,34 @@ public:
#if !defined(NDEBUG) || (FILAMENT_DEBUG_COMMANDS >= FILAMENT_DEBUG_COMMANDS_ENABLE)
// For now, simply pass the method name down as a string and throw away the parameters.
// This is good enough for certain debugging needs and we can improve this later.
#define DEBUG_COMMAND_BEGIN(methodName, sync, ...) mDriver->debugCommandBegin(this, sync, #methodName)
#define DEBUG_COMMAND_END(methodName, sync) mDriver->debugCommandEnd(this, sync, #methodName)
#define DEBUG_COMMAND_BEGIN(methodName, sync, ...) mDriver.debugCommandBegin(this, sync, #methodName)
#define DEBUG_COMMAND_END(methodName, sync) mDriver.debugCommandEnd(this, sync, #methodName)
#else
#define DEBUG_COMMAND_BEGIN(methodName, sync, ...)
#define DEBUG_COMMAND_END(methodName, sync)
#endif
class CommandStream {
// Dispatcher could be a value (instead of pointer), which saves a load when writing commands
// at the expense of a larger CommandStream object (about ~400 bytes)
Dispatcher* mDispatcher = nullptr;
Driver* mDriver = nullptr;
CircularBuffer* UTILS_RESTRICT mCurrentBuffer = nullptr;
#ifndef NDEBUG
// just for debugging...
std::thread::id mThreadId{};
#endif
bool mUsePerformanceCounter = false;
template<typename T>
struct AutoExecute {
T closure;
inline AutoExecute(T&& closure) : closure(std::forward<T>(closure)) {}
inline explicit AutoExecute(T&& closure) : closure(std::forward<T>(closure)) {}
inline ~AutoExecute() { closure(); }
};
public:
CommandStream(Driver& driver, CircularBuffer& buffer) noexcept;
CommandStream(CommandStream const& rhs) noexcept = delete;
CommandStream& operator=(CommandStream const& rhs) noexcept = delete;
public:
#define DECL_DRIVER_API(methodName, paramsDecl, params) \
inline void methodName(paramsDecl) { \
DEBUG_COMMAND_BEGIN(methodName, false, params); \
using Cmd = COMMAND_TYPE(methodName); \
void* const p = allocateCommand(CommandBase::align(sizeof(Cmd))); \
new(p) Cmd(mDispatcher->methodName##_, APPLY(std::move, params)); \
new(p) Cmd(mDispatcher.methodName##_, APPLY(std::move, params)); \
DEBUG_COMMAND_END(methodName, false); \
}
@@ -259,16 +223,16 @@ public:
AutoExecute callOnExit([=](){ \
DEBUG_COMMAND_END(methodName, true); \
}); \
return apply(&Driver::methodName, *mDriver, std::forward_as_tuple(params)); \
return apply(&Driver::methodName, mDriver, std::forward_as_tuple(params)); \
}
#define DECL_DRIVER_API_RETURN(RetType, methodName, paramsDecl, params) \
inline RetType methodName(paramsDecl) { \
DEBUG_COMMAND_BEGIN(methodName, false, params); \
RetType result = mDriver->methodName##S(); \
RetType result = mDriver.methodName##S(); \
using Cmd = COMMAND_TYPE(methodName##R); \
void* const p = allocateCommand(CommandBase::align(sizeof(Cmd))); \
new(p) Cmd(mDispatcher->methodName##_, RetType(result), APPLY(std::move, params)); \
new(p) Cmd(mDispatcher.methodName##_, RetType(result), APPLY(std::move, params)); \
DEBUG_COMMAND_END(methodName, false); \
return result; \
}
@@ -276,15 +240,12 @@ public:
#include "DriverAPI.inc"
public:
CommandStream() noexcept = default;
CommandStream(Driver& driver, CircularBuffer& buffer) noexcept;
// This is for debugging only. Currently CircularBuffer can only be written from a
// This is for debugging only. Currently, CircularBuffer can only be written from a
// single thread. In debug builds we assert this condition.
// Call this first in the render loop.
inline void debugThreading() noexcept {
#ifndef NDEBUG
mThreadId = std::this_thread::get_id();
mThreadId = utils::ThreadUtils::getThreadId();
#endif
}
@@ -313,9 +274,22 @@ public:
private:
inline void* allocateCommand(size_t size) {
assert_invariant(mThreadId == std::this_thread::get_id());
return mCurrentBuffer->allocate(size);
assert_invariant(utils::ThreadUtils::isThisThread(mThreadId));
return mCurrentBuffer.allocate(size);
}
// We use a copy of Dispatcher (instead of a pointer) because this removes one dereference
// when executing driver commands.
Driver& UTILS_RESTRICT mDriver;
CircularBuffer& UTILS_RESTRICT mCurrentBuffer;
Dispatcher mDispatcher;
#ifndef NDEBUG
// just for debugging...
std::thread::id mThreadId{};
#endif
bool mUsePerformanceCounter = false;
};
void* CommandStream::allocate(size_t size, size_t alignment) noexcept {
@@ -340,7 +314,6 @@ PodType* CommandStream::allocatePod(size_t count, size_t alignment) noexcept {
return static_cast<PodType*>(allocate(count * sizeof(PodType), alignment));
}
} // namespace backend
} // namespace filament
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_PRIVATE_COMMANDSTREAM_H
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2022 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.
*/
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_DISPATCHER_H
#define TNT_FILAMENT_BACKEND_PRIVATE_DISPATCHER_H
#include <stdint.h>
namespace filament::backend {
class Driver;
class CommandBase;
/*
* Dispatcher is a data structure containing only function pointers.
* Each function pointer targets code that unpacks the arguments to the driver's method and
* calls it.
*
* Dispatcher's function pointers are populated during initialization and no CommandStream calls
* can be made before that.
*
* When a command is inserted into the stream, the corresponding function pointer is copied
* directly into CommandBase from Dispatcher.
*/
class Dispatcher {
public:
using Execute = void (*)(Driver& driver, CommandBase* self, intptr_t* next);
#define DECL_DRIVER_API_SYNCHRONOUS(RetType, methodName, paramsDecl, params)
#define DECL_DRIVER_API(methodName, paramsDecl, params) Execute methodName##_;
#define DECL_DRIVER_API_RETURN(RetType, methodName, paramsDecl, params) Execute methodName##_;
#include "DriverAPI.inc"
};
} // namespace filament::backend
#endif //TNT_FILAMENT_BACKEND_PRIVATE_DISPATCHER_H
@@ -17,23 +17,14 @@
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_DRIVER_H
#define TNT_FILAMENT_BACKEND_PRIVATE_DRIVER_H
#include <backend/BufferDescriptor.h>
#include <backend/CallbackHandler.h>
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
#include <backend/PipelineState.h>
#include <backend/PixelBufferDescriptor.h>
#include <backend/PresentCallable.h>
#include <backend/TargetBufferInfo.h>
#include "private/backend/DriverApiForward.h"
#include "private/backend/Program.h"
#include "private/backend/SamplerGroup.h"
#include <utils/compiler.h>
#include <utils/Log.h>
#include <functional>
#include <stdint.h>
@@ -49,8 +40,13 @@
#define FILAMENT_DEBUG_COMMANDS FILAMENT_DEBUG_COMMANDS_NONE
namespace filament {
namespace backend {
namespace filament::backend {
class BufferDescriptor;
class CallbackHandler;
class PixelBufferDescriptor;
class Program;
class SamplerGroup;
template<typename T>
class ConcreteDispatcher;
@@ -59,27 +55,32 @@ class CommandStream;
class Driver {
public:
static size_t getElementTypeSize(ElementType type) noexcept;
virtual ~Driver() noexcept;
static size_t getElementTypeSize(ElementType type) noexcept;
// called from the main thread (NOT the render-thread) at various intervals, this
// is where the driver can execute user callbacks.
virtual void purge() noexcept = 0;
virtual ShaderModel getShaderModel() const noexcept = 0;
virtual Dispatcher& getDispatcher() noexcept = 0;
// Returns the dispatcher. This is only called once during initialization of the CommandStream,
// so it doesn't matter that it's virtual.
virtual Dispatcher getDispatcher() const noexcept = 0;
// called from CommandStream::execute on the render-thread
// the fn function will execute a batch of driver commands
// this gives the driver a chance to wrap their execution in a meaningful manner
// the default implementation simply calls fn
virtual void execute(std::function<void(void)> fn) noexcept;
virtual void execute(std::function<void(void)> const& fn) noexcept;
// This is called on debug build, or when enabled manually on the backend thread side.
virtual void debugCommandBegin(CommandStream* cmds, bool synchronous, const char* methodName) noexcept = 0;
virtual void debugCommandEnd(CommandStream* cmds, bool synchronous, const char* methodName) noexcept = 0;
virtual void debugCommandBegin(CommandStream* cmds,
bool synchronous, const char* methodName) noexcept = 0;
virtual void debugCommandEnd(CommandStream* cmds,
bool synchronous, const char* methodName) noexcept = 0;
/*
* Asynchronous calls here only to provide a type to CommandStream. They must be non-virtual
@@ -101,7 +102,6 @@ public:
#include "private/backend/DriverAPI.inc"
};
} // namespace backend
} // namespace filament
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_PRIVATE_DRIVER_H
@@ -246,11 +246,6 @@ DECL_DRIVER_API_R_N(backend::SwapChainHandle, createSwapChainHeadless,
uint32_t, height,
uint64_t, flags)
DECL_DRIVER_API_R_N(backend::StreamHandle, createStreamFromTextureId,
intptr_t, externalTextureId,
uint32_t, width,
uint32_t, height)
DECL_DRIVER_API_R_0(backend::TimerQueryHandle, createTimerQuery)
@@ -293,6 +288,7 @@ DECL_DRIVER_API_SYNCHRONOUS_N(bool, isRenderTargetFormatSupported, backend::Text
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isFrameBufferFetchSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isFrameBufferFetchMultiSampleSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isFrameTimeSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isAutoDepthResolveSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(uint8_t, getMaxDrawBuffers)
DECL_DRIVER_API_SYNCHRONOUS_0(math::float2, getClipSpaceParams)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, canGenerateMipmaps)
@@ -460,14 +456,6 @@ DECL_DRIVER_API_N(readPixels,
uint32_t, height,
backend::PixelBufferDescriptor&&, data)
DECL_DRIVER_API_N(readStreamPixels,
backend::StreamHandle, sh,
uint32_t, x,
uint32_t, y,
uint32_t, width,
uint32_t, height,
backend::PixelBufferDescriptor&&, data)
/*
* Rendering operations
* --------------------
@@ -483,7 +471,8 @@ DECL_DRIVER_API_N(blit,
DECL_DRIVER_API_N(draw,
backend::PipelineState, state,
backend::RenderPrimitiveHandle, rph)
backend::RenderPrimitiveHandle, rph,
uint32_t, instanceCount)
#pragma clang diagnostic pop
@@ -17,15 +17,12 @@
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_DRIVERAPIFORWARD_H
#define TNT_FILAMENT_BACKEND_PRIVATE_DRIVERAPIFORWARD_H
namespace filament {
namespace backend {
namespace filament::backend {
class CommandStream;
using DriverApi = CommandStream;
} // namespace backend
} // namespace filament
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_PRIVATE_DRIVERAPIFORWARD_H
@@ -61,7 +61,7 @@ public:
*/
template<typename D, typename ... ARGS>
Handle<D> allocateAndConstruct(ARGS&& ... args) noexcept {
Handle<D> h{ allocateHandle(sizeof(D)) };
Handle<D> h{ allocateHandle<sizeof(D)>() };
D* addr = handle_cast<D*>(h);
new(addr) D(std::forward<ARGS>(args)...);
#if HANDLE_TYPE_SAFETY
@@ -84,7 +84,7 @@ public:
*/
template<typename D>
Handle<D> allocate() noexcept {
Handle<D> h{ allocateHandle(sizeof(D)) };
Handle<D> h{ allocateHandle<sizeof(D)>() };
#if HANDLE_TYPE_SAFETY
D* addr = handle_cast<D*>(h);
mLock.lock();
@@ -167,7 +167,7 @@ public:
}
#endif
p->~D();
deallocateHandle(handle.getId(), sizeof(D));
deallocateHandle<sizeof(D)>(handle.getId());
}
}
@@ -249,23 +249,49 @@ private:
utils::LockingPolicy::SpinLock>;
#endif
// this is inlined because we're always called with a constexpr size
HandleBase::HandleId allocateHandle(size_t size) noexcept {
void* p = mHandleArena.alloc(size);
if (UTILS_LIKELY(p)) {
return pointerToHandle(p);
// allocateHandle()/deallocateHandle() selects the pool to use at compile-time based on the
// allocation size this is always inlined, because all these do is to call
// allocateHandleInPool()/deallocateHandleFromPool() with the right pool size.
template<size_t SIZE>
HandleBase::HandleId allocateHandle() noexcept {
if constexpr (SIZE <= P0) { return allocateHandleInPool<P0>(); }
if constexpr (SIZE <= P1) { return allocateHandleInPool<P1>(); }
return allocateHandleInPool<P2>();
}
template<size_t SIZE>
void deallocateHandle(HandleBase::HandleId id) noexcept {
if constexpr (SIZE <= P0) {
deallocateHandleFromPool<P0>(id);
} else if constexpr (SIZE <= P1) {
deallocateHandleFromPool<P1>(id);
} else {
return allocateHandleSlow(size);
deallocateHandleFromPool<P2>(id);
}
}
// this is inlined because we're always called with a constexpr size
void deallocateHandle(HandleBase::HandleId id, size_t size) noexcept {
// allocateHandleInPool()/deallocateHandleFromPool() is NOT inlined, which will cause three
// versions to be generated, one for each pool. Because the arena is synchronized,
// the code generated is not trivial (even if it's not insane either).
template<size_t SIZE>
UTILS_NOINLINE
HandleBase::HandleId allocateHandleInPool() noexcept {
void* p = mHandleArena.alloc(SIZE);
if (UTILS_LIKELY(p)) {
return pointerToHandle(p);
} else {
return allocateHandleSlow(SIZE);
}
}
template<size_t SIZE>
UTILS_NOINLINE
void deallocateHandleFromPool(HandleBase::HandleId id) noexcept {
if (UTILS_LIKELY(isPoolHandle(id))) {
void* p = handleToPointer(id);
mHandleArena.free(p, size);
mHandleArena.free(p, SIZE);
} else {
deallocateHandleSlow(id, size);
deallocateHandleSlow(id, SIZE);
}
}

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