* Add the ability to modify clip space coordinates in the vertex shader
This introduces MaterialVertexInputs.clipSpaceTransform, a mat4 that
is applied to gl_Position before exiting the vertex stage.
* Address code review comments
* Lower limit from API 21 to API 19
This was requested by an internal application. API 19 is when OpenGL
ES 3.0 support was added so there is no good reason for us to not
support this API level. The only trick is to avoid referring to the
glTexStorage2DMultisample symbol directly as it only exists in 3.1.
* Compile out code we never use
* Use reflection to handle shared EGL contexts pre-API 21.
* Remove comment
* More fixes required to run on API level 19
- dlym() fails for ashmem on API 19, so we only try on API 26+ instead.
- Older emulation for OpenGL ES 3.0 returns error states for valid API calls so we need to clear the GL error bit before we create the GL driver.
- Activity lifecycle changes since API 19 would cause animations to keep running and to reference destroyed objects.
- EGLContext.getNativeHandle() is new in API 21, we need to use reflection on API 19. The new code path uses the class loading trick to avoid a bytecode verification error on API 19.
* Filament now runs properly on API level 19
This commit adds a new api_level() API to libutils which can be used to
query the platform's API level. On Android it works as expected, other
platforms currently return 0.
This is to allow designated aggregate initialization in C++20.
We do this because we have been relying on C99 designated
initialization, which is only supported by clang, other compilers need
c++20 to get a similar functionality. Therefore, we now try to limit
Ourselves to C++20 rules.
This could break existing code, since now SamplerParams needs to be
zero-initialized:
SamplerParams p{};
This is generally not an issue because the intended use is:
doSomethingWithSamplerParams({
.filterMag = LINEAR,
});
the C++ standard says:
if T is a class type with a default constructor that is neither
user-provided nor deleted (that is, it may be a class with an
implicitly-defined or defaulted default constructor), the object
is zero-initialized and then it is default-initialized if it has a
non-trivial default constructor
Unfortunately, MSVC always calls the default constructor, even if it
is trivial, which breaks constexpr-ness.
To workaround this, we're always zero-initializing TVecN<>
Also removed constexpr from default constructors, since they never can
be constexpr as they're not initializing the vector.
* Add new setExposure(float) API on Camera
This API can be used to set a specific exposure value. For instance:
camera.setExposure(1.0)
Will set the exposure to 1.0 (or ISO 100, apeture 1.0 and shutter speed 1.2s).
This can be useful to match the lighting setup of other engines/tools. Setting
the exposure to 1.0 can for instance be used to treat lights as being unitless
(a directional light could have a strength of 2.0 for instance).
Fixes#1667
* Update release notes
* Fix Java build error
* Fix Web bindings
We need to document the backend headers that are public.
Added documentation for:
- DriverEnums.h
- BufferDescriptor.h
- PixelBufferDescriptor.h
Disabled doxygen for public headers of backend that don't need to
be public for filament's API.
Also improved documentation for:
- LightManager.h
- RenderTarget.h
- TextureSampler.h
This is a similar fix to the previous vector fix. Commutative
operations now always return the same type and the operations are
carried out in the precision resulting from following traditional
C++ rules.
It used to be that operations e.g. like:
float3{} + double{} would be computed as
float3{} + float3{double{}} instead of
float3{} + double3{double{}}
I other words, when an implicit conversion was involved on the right
it would be converted to the left side’s type, possibly losing
precision.
Another problem was that swiping the operands could produce different
Results, e.g.:
float3{1} * 5.0 -> float3{5.0f}
5.0 * float3{1} -> double3{5.0}
This is no longer the case, now both expressions would return a double3.
Note:
float3 r{};
r *= 5;
Is now equivalent to:
r[0] *= 5;
r[1] *= 5;
r[2] *= 5;
Instead of before:
r[0] *= 5.0f;
r[1] *= 5.0f;
r[2] *= 5.0f;
We now follow the same rules than for basic types, when performing
mixed-precision operations, e.g.:
float3 + double3 -> double3
double3 + float3 -> double3
dot(float3, double3) -> double
In particular, e.g. swapping the arguments to arithmetic operations
now always yields to the same result type (before, float3 + double3
would not return the same type than double3 + float3).
To prevent an excess of variants, sometimes our vertex shaders declare
inputs that they never read from. For example, our skin-and-morph
variant might never read from the skinning attribute, but still declares
the input.
This PR is a sister to #1663, which is a fix for #1525.
See also #1279.
We now use GENERAL layout for depth-sampled images in order to support
the SSAO use case of simultaneous binding + sampling.
We may be able to optimize this in the future by enhancing DriverAPI
so that it feeds more information into the render pass.
Fixes#1627, #1649.
We now inverse the face winding order based on the determinant of
each render primitive world's transform. This prevents front/back faces
to be reversed when using a left-handed basis, after transform.
Fix#1520
Inspired by our recent scissor change (#1639) but motivated by gltfio,
which was forced to create a ton of ubershaders (see #1562).
Tested with:
gltf_viewer -u ../glTF-Sample-Models/2.0/TextureSettingsTest/glTF/TextureSettingsTest.gltf
This is nicer because this way the methods that don't match don't
even exist. Also make it better when editing code with a C++ aware
ide.
Also use the less verbose std::enable_if_t<>
We now have OpenGLContext which only tracks the OpenGL state.
It exposes an API very similar to OpenGL and does all the state
tracking. Currently, it doesn't expose non state-changing APIs
(e.g. draw methods) and only implements the state-changing API we
need (to track the state of).
If you tried removing `culling: none` from any post-process materials,
everything would be fine in GL but Vulkan would be black because
our full-screen triangle was back-facing.
Continue reading only if you thrive in absurd situations.
- Metal and OpenGL define clip space as Y-up whereas Vulkan is Y-down.
- Metal and Vulkan define tex coords as Y-down whereas OpenGL is Y-up.
* Add Android presubmit
* Build Android on Linux, macOS targets have NDK 18 only
* Consolidate workflows and jobs
* Try to build Android on macOS
* Fix typo
* Cleanup scripts
* Try NDK side by side if NDK bundle has the wrong version
* Simplify logic
* Fix NDK logic
* Only update the NDK when necessary
* Fix typo
* Update required NDK version
* Favor NDK side-by-side
* Remove support for obsolete NDK bundle, require NDK side-by-side
* Install the NDK side by side when missing
This prevents values like NONE or COLOR which are very generic
names to collide with other classic enums. It also forces us to be
specific about what we're doing when converting to bitfields.
Also added a utility to easily enable any enum or enum class to
support binary operation (i.e. Bitmask contract), e.g.:
template<> struct utils::EnableBitMaskOperators<Foo> : public std::true_type{};
gives all binary operators to 'Foo'. Foo must be an enum.
Also added any() and none() convenience to convert an enum to a boolean.
This simplifies its usage at call sites at lot.
The C++ ctor was needed before to create uninitialized objects, which
was needed in SamplerGroup. Instead we use a custom 'static_vector'
(instead of std::array), this actually makes SamplerGroup's
implementation clearer.
static_vector<> is just a fixed-capacity, fixed-storage dynamic
vector. we currently don't expose it and implement only what we
need.
The suzanne Vulkan demo was asserting because `setViewportScissor` can
only be called within a render pass, which means that
`MaterialInstance::use` can only be called within a render pass.
We probably need a better way to enforce these rules...
Every time ninja invoked CMake, we were unconditionally regenerating
all of our "licenses.inc" files which caused a ton of re-compiles.
Before the change, building after touching `ubershader.mat.in` took over
a minute, now it takes 20 seconds.
The CMake "file" commands are bad. The CMake documentation says:
If the file is a build input, use the configure_file() command
to update the file only when its content changes.
Some buffers (like animation data) do not contain any vertex data
but web-based clients still need to know about this.
This interface is much simpler than the bindings lists, and in fact
we might remove the binding lists in the future to simplify the API.
Fixes#1593.
some driver don't support all float buffers as rendertarget, so we
improve the backends (opengl in this PR) to return what it actually
supports and we update the client (filament) to take that into
account when making decisions.
by using variadic macros we can greatly simplify the macros
definitions for declaring the backend API.
in particular we don't need a macro per number-of-argument, this is
now done automatically.
Unfortunately, we still can't handle zero-argument declarations, so
we keep the _0 variants.
This performs surgical modification of the IFF chunks rather than
invoking filamat from within matdbg. Low-level direct manipulation
(bypassing optimization passes etc) allows us to diagnose issues with
the shading pipeline.
This CL also adds keystroke bindings to the Monaco editor. You can
press Cmd+S to rebuild the current materials, or use Ctrl+Arrow to
navigate between shader variants and materials.
In a subsequent CL I will add a README that describes how this works in
detail, it will include a list of limitations and a feature wishlist.
We now check for FILAMENT_ENABLE_MATDBG and simply skip the draw call
when the program is invalid. The initial error message is still dumped
to the console, but we will not terminate or dump an infinite cascade of
error messages.
This only adds Engine-side support for edits. The debugger client will
be enhanced in another PR. This works by simply clearing the program
cache and swapping out the MaterialParser. Neat!
However, there are some gotchas:
- The DebugServer callback is triggered on another thread so to be safe
we defer the swap until the subsequent call to getProgram().
- The getProgram() method is const but in reality it can insert entries
into a mutable cache. This CL makes the constness of it even more
misleading by applying edits.
- The edit operation will leak the old HwProgram but I feel this is
fine because simplicity is crucial for injected behavior and this is
a developer-only feature.
Texture are special resources that can be read in different ways; either as
attachment (read) or sampled (sample), the user must now declare explicitly if she intends
to sample from a texture.
sample() implies read() so there is no need to call both.
This was already the case, as read() used to take a boolean, essentially meaning the same
thing. However, the bool didn't make sense for non-texture resources.
This also simplifies the implementation.
the framegraph will figure it out automatically from the
rendertarget sample count. this is done during resolve(), and after
moveResource is taken into account (so this works with imported and
moved resources).
when creating a rendertarget, if the sample count is not specified,
any existing target with the same attachment will match.
this simplifies both the user and implementation.
getRenderTargetDescriptor() now takes a RenderTargetHandle instead
of a texture handle.
This can be enabled by using the Tracking::Debug policy,
currently this just fills allocation on alloc() and free(),
which is useful to help detect access to uninitialized memory
and use after free.
Now enabled by default in libfilament allocators on debug builds.
This caught uninitialized access in the froxelizer.
I tested this with the problem model and a couple other models.
This bug is inherited from cgltf_node_transform_local, so I will
upstream the fix. There are two ways to see that the new math is
correct:
1) Look at decomposeMatrix and note that scales belong to rows,
not columns.
2) Look at the Brandon Jones implementation:
http://glmatrix.net/docs/mat4.js.html#line1079Fixes#1519.
We were storing pointer to RenderTarget objects that were allocated
in a vector<>, which obviously is not safe.
This didn't cause any issue most of the time because our allocator is
a linear allocator.
We've been using STB for a while now and we already include a JPEG
decoder in our wasm bundle. This removes some vestigial code that was
getting in the way.
Fixes#1565.
Performing `base + offset` pointer arithmetic is only allowed when `base` itself is not nullptr. In other words, the compiler is assumed to allow that `base + offset` is always non-null, which an upcoming compiler release will do in this case. The result is that CommandStream.cpp, which calls this in a loop until the result is nullptr, will never terminate (until it runs junk data and crashes).
Avoid this by using intptr_t instead of actual pointers (i.e. char*), which seems to avoid this failure.
* Improve materials under white furnace test
Two major changes:
- Mobile target now implements a cheaper variant of the off specular
peak bias (which moves the reflected vector towards the normal).
This greatly helps with rough surfaces that may otherwise point
toward a bright part of the IBL.
- The indirect diffuse love is now properly attenuated to avoid adding
the energy reflected by the specular layer. This allows dielectrics
to be correctly energy conserving under a white furnace.
- Tweak the (hacky) clear coat layer attenuation to behave properly
under a white furnace.
* Use the same reflected vector modification everywhere
* Add #include preprocessing to filamat and matc
* Update RELEASE_NOTES
* Fix RELEASE_NOTES
* Use final instead of virtual / override
* Clarify comments
* Use pure virtual for includer functions
* Use a callback instead of an interface
* Rename Includer.h to IncludeCallback.h
* Update comment
matdbg is now linked into the Filament Engine in debug config (allowing
live inspection of GLSL / SPIRV) and into the matinfo tool (to support
the --web-server option).
In both cases, the library spins up a small web server that listens to
http://localhost:8080. You can run any Filament app and attach to it.
The web client caches all material information. This allows the user to
close an atttached Filament app, and the web app will continue to
function properly (useful for crash diagnosis). Moreover the user can
launch a second Filament app and the web client will add its materials
to the existing list (useful when comparing two Filament apps).
For now this only supports inspection, not editing. Some of the material
info such as required attributes is not yet displayed but this will be
easy to flesh out in a subsequent PR.
This is a dependency of our upcoming web-based material debugger. This
CL also includes `tnt/CMakeLists.txt`, which builds a static lib in a
minimal configuration that enables WebSocket support. The entire library
is built from only 4 files:
${PUBLIC_HDR_DIR}/CivetServer.h
${PUBLIC_HDR_DIR}/civetweb.h
${SRC_DIR}/civetweb.c
${SRC_DIR}/CivetServer.cpp
access to resources now needs to be done explicitly before calling
useRenderTarget(). This simplifies things and is needed for more
simplifications to come.
This enhances the exisiting matc option "--debug" so that it includes
debug information in the resulting SPIR-V.
Previously we tied this to the build configuration which isn't very
flexible. Moreover this needs to be orthogonal to shader opts, because
we often need to debug problems that arise from optimization.
This CL also gives meaningful names to the ubershader materials and
fixes up the new matinfo analysis so that it prints the entire SPIRV
chunk that corresponds to each potentially problematic GLSL codeline.
Motivated by #1516.
This is an improved workaround for a known limitation with Vulkan
drivers on Android P. The offending SPIR-V sequence was introduced
during shader optimization and can be avoided by using full precision
for certain variables.
This adds a new option to matinfo that does some very dumb regex-based
analysis on the disassembled SPIR-V, then dumps out transpiled GLSL
that has annotations added to the end of some codelines. For example:
```glsl
float luminance(vec3 linear) // POTENTIAL MIXED PRECISION %49 = OpDot %float %linear %48; relaxed = %49 %linear
{
return dot(linear, vec3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875));
}
```
The code currently tries to find potential mixed precision but does not
do the right thing yet for pointers and structs. This is just a starting
point to help diagnose problem areas in our generated SPIR-V.
* Update Froxelizer.h
Fix this error when building with msvc from vs2019
error C2926: 'filament::details::Froxelizer::FroxelEntry::<unnamed-tag>::offset': a default member initializer is not allowed for a member of an anonymous struct within a union
* Fix some compilation issues with vs2019/msvc
Program.cpp:
1>C:\greg\github\filament\filament\backend\src\Program.cpp(28,42): error C2610: 'filament::backend::Program::Program(void) noexcept': is not a special member function or comparison operator which can be defaulted
1>C:\greg\github\filament\filament\backend\src\Program.cpp(28,42): message : exception specification does not match the implicitly declared specification.
GLUtils.h: __PRETTY_FUNCTION__ macro is clang specific. Use MSVC equivalent
Color.h: fix warning
* #1493 - inline constructor in definition as requested by @romainguy
* #1493 "move this #define inside the #else below" as requested
* #1493 revert last change which causes compilation failures on other platforms.
provide empty implementation of Program::Program() in Program.cpp
* More fixes for building with vs2019/msvc
* #1500 use consistent macro definition syntax (@bejado)
* #1500 simplify DEBUG_COMMAND macro as requested by @pixelflinger
* #1500 use `{ 0 }` which is accepted by Visual Studio (` = 0 ` is not accepted)
* #1500 remove incorrect UTILS_RESTRICT alltogether
We're only caching textures (not render targets yet), and we're
evicting cache entries older than 30 allocations.
This should cut down on texture allocation / gl calls.
The cache should get in a stable state very quickly (less than half
second).
* Update Froxelizer.h
Fix this error when building with msvc from vs2019
error C2926: 'filament::details::Froxelizer::FroxelEntry::<unnamed-tag>::offset': a default member initializer is not allowed for a member of an anonymous struct within a union
* Fix some compilation issues with vs2019/msvc
Program.cpp:
1>C:\greg\github\filament\filament\backend\src\Program.cpp(28,42): error C2610: 'filament::backend::Program::Program(void) noexcept': is not a special member function or comparison operator which can be defaulted
1>C:\greg\github\filament\filament\backend\src\Program.cpp(28,42): message : exception specification does not match the implicitly declared specification.
GLUtils.h: __PRETTY_FUNCTION__ macro is clang specific. Use MSVC equivalent
Color.h: fix warning
* #1493 - inline constructor in definition as requested by @romainguy
* #1493 "move this #define inside the #else below" as requested
* #1493 revert last change which causes compilation failures on other platforms.
provide empty implementation of Program::Program() in Program.cpp
This removes the samples/envs folder and replaces these KTX files with a
build step that is driven by CMake / gradle / bash, depending on
platform.
This makes it easier to use IBL files that are generated by the latest
and greatest version of cmake.
Fix this error when building with msvc from vs2019
error C2926: 'filament::details::Froxelizer::FroxelEntry::<unnamed-tag>::offset': a default member initializer is not allowed for a member of an anonymous struct within a union
Some drivers have performance issues when repeatedly (once per frame)
allocating and destroying render targets, so we will
re-introduce a cache for that.
this just adds the hooks for the cache.
We use R11F_G11F_B10F for HDR so we should stop checking for compressed
IBL files.
Also, make the glTF sample on web more consistent with the default
settings used by gltf_viewer on native and use venetian_crossroads
instead of syferfontein.
We should not use the address of a stdlib function for BufferDescriptor
callbacks. With emcc this compiles without warnings or errors, but
produces incorrect code that causes intermittent out-of-memory errors at
run time.
* Use GL_EXTENSION for GL_OES_EGL_image_external_essl3
A prior change that reworked some code incorrectly attempted to
use the existing EGL extensions to set a GL extension boolean.
Added additional GL extension code.
* Fix typo
* Fix typo
Avoid enabling scissors when the viewport is the same size as the
buffer. On Adreno devices, running clearWithGeometryPipe adds
three additional unresolves for each bin.
VkFramebuffer requires its attachments to have only one miplevel each,
but our VulkanRenderTarget wrapper was sharing the VkImageView that
associated with the underlying texture object.
This fixes up VulkanRenderTarget so that it owns a unique VkImageView
that is pinned to a specific miplevel.
We now build three gltfio libraries:
- gltfio_core ....... lightweight library with ubershaders
- gltfio ............ uses filamat to generate materials at runtime
- gltfio_pipeline ... depends on path tracer functionality
This fixes one of the bugs seen with `gltf-bloom` on Android.
We already dynamically map Filament's DEPTH24 format to either
VK_FORMAT_D32_SFLOAT or VK_FORMAT_X8_D24_UNORM_PACK32, depending on
the platform. Therefore we should return `true` when asked if the
backend supports DEPTH24. Otherwise the client will not be able to
create a depth texture.
(1) Sometimes (but not always!) gltfio-android was failing to build due
to two missing ANativeWindow functions. Linking in "android" seems to
fix this, and is consistent with libfilament-jni.
(2) Improve our "build.sh -c" utility by clobbering some additional
Android build directories. This is especially useful after
adding "-Pextra_cmake_args=-DFILAMENT_SUPPORTS_VULKAN=ON", otherwise
Gradle will try to use a cached CMake configuration.
By design, VulkanRenderTarget has weak references to its attachments and
does not manage any hardware resources. Therefore, when we start
rendering to a particular render target, we need to inform
VulkanDisposer that the command buffer has acquired a reference to the
underlying textures. This prevents the possibility of the texture being
destroyed while still in use.
This fixes#1450 although we should also add a render target pool for
best performance.
This works by aliasing CUSTOM0 - CUSTOM7 to morphing attributes, and by
extending our existing skinning variant.
This PR was tested against some upcoming changes to gltfio.
Issue #1149, #1417
When processing very high dynamic range environments, the importance
sampling code falls appart, it becomes a user choice to decide if
prefilter importance sampling is better or worse than just regular
importance sampling -- both are usually bad.
--ibl-no-prefilter gives the user this choice.
In the case where we have 2 cores, we would spawn only one thread in
the thread pool. If that thread got to try to steal() from another
thread before the main thread was adopted, it would end-up always
trying to steal from itself and enter an infinite loop.
This seems to happen during windows builds.
This combines two constants into one, and changes it into a value that
is actually correct. :)
Technically the movement of the CUSTOM attributes will change the layout
qualifier and therefore merits a materials version bump, however custom
attributes were only recently introduced so this seems unnecessary.
Did some quick testing with 3 samples: gltf_viewer, lucy_bloom, and
point_sprites.
Clamping is now disabled by default in cmgen, there is a new option
to enable it "--clamp".
Automatic SH windowing is also enabled by default and can be controled
with the "--sh-window" option. Accepted parameters are "no" to disable
windowing, "auto" for automatic windowing or a number to specify the
cutoff band.
auto windowing only works for 1, 2, and 3 bands.
Currently we're arbitrarily clamping environments to 16384 because both
the pre-filtering and SH algorithms can't handle very larger dynamic
ranges. Instead of clamping, we now tonemap, which is a little bit better.
It turns out that most of libmath couldn't be used in constexpr
expression due to our use of union{}. The C++ standard requires that
all accesses to a union{} in a constexpr expression be the same
element.
Also because libm and cmath are not constexpr some functions such
as length() or normalize() can't be constexpr. The same is true for
anything needing things like sqrt, cos, sin, ceil, floor.
This change mainly does the following:
- replace all accesses to vector elements by operator[]
(this ensure all of libmath uses the same union element)
- avoid use of std::min / std::max / std::abs
- avoid uninitialized variables, which can't be constexpr
- remove 'constexpr' keyword on functions that can never be
It is now possible to write things like:
constexpr mat4f I = inverse(
transpose(mat4f::translation(float3{ 1, 2, 3 })
* mat4f::scaling(4)));
--sh-window=band, -w band : this low-pass-filters the environment
such that bands above 'band' are zero. This can be used to reduce ringing
when the source environment has high frequencies
--noclamp : turns off clamping before processing the cube map
This is still work in progress.
The conversion factors from radiance to irradiance where wrong.
The bug above was found while refactoring the code to be clearer. Now
the method that computes the coefficients for the shader calls the
regular SH code and applies all the appropriate factors on that.
With this change the options "--sh-shader" and "-sh=3 -i" won't
produce the same result because --sh-shader includes the lambertian
diffuse. "--sh" now always produces actual SH coefficients.
This is a prep step for the upcoming morph feature and does not require
a bump to our material version number.
Stay tuned for a new sample app that demonstrates this feature.
this is because the JobSystem's queue works as a LIFO, by creating
jobs in reverse (memory) order, we attempt to help streaming to
the d-cache on that threads -- until the point where
jobs are stolen.
we also execute the last job immediately instead of creating a job
for it -- since we're already in a job.
- parallel_for doesn't use recursion anymore to create the "leaf"
jobs, this is now done linearly on N thread (one thread per CPU).
This uses less stack space, and reduces miss-predicted branches.
- remove almost all SYSTRACE calls because they have a huge impact
on things like parallel_for() and are misleading. They can be
enabled again by setting HEAVY_SYSTRACE to true.
- we simplify the waiting code by using only a single
condition variable instead of two.
- wait() now behaves just like a looper, it will process jobs until
the one it's waiting for finishes -- before it could just sit there
(the idea was that the job would finish quickly, but that's not always
the case).
- we also make sure to never call notify_n() when it's not needed.
We track how many waiters we have and use that to decide if we need
to notify().
notify is pretty slow on all architectures, even on linux it's always
a syscall, so it's better to avoid it.
- don't use stand-alone fences, makes things ugly for no real benefit
- refactored the code a bit, hopefully it's more clear.
If the client opts in to "recomputeBoundingBoxes", then we manually
compute a bounding box that ignores the glTF min / max annotations.
This computation was erroneously including the transform of the injected
root node, which is not part of the model.
This could cause a problem when creating the asset, then immediately
positioning it with its injected root node before the ResourceLoader
is done downloading vertex buffers.
The Work-stealing dequeue indices could wrap around after ~2 billion
calls to steal(). This could probably be achieved in a few hours.
By using 64-bits indices, we avoid the problem entirely.
This uses strtof rather than stringstream and provides a common location
that can be leveraged by the upcoming JNI bindings.
Note that this new method lives in KtxBundle rather than KtxUtility. The
latter creates Filament textures and therefore does not get built into
libimage.
For jobs with that do very little work, the jobsystem can introduce
a lot of overhead, we mitigate this by:
- don't wake-up worker threads when scheduling several very small jobs,
like when scheduling the per-face jobs.
- don't wait for per-face jobs to finish -- we only did that to avoid
a copy of the job's data.
- don't use multi-threading at all if the job has too little work. We
evaluate the work using the scanline length and number of samples.
Discussed this feature with Mathias, we decided to create
MaterialInstance Java wrappers on the fly, and create Material Java
wrappers lazily. This is simple and avoids caching the wrapper objects,
which might otherwise lead to complexity and bugs.
Note that gltfio creates material instances behind the scenes, so this
feature is particularly useful for gltfio clients.
Previously we used the <T=float> template instantiation of setParameter
when the client specified FLOAT4. This resulted in the lower layer
adding needless padding, thus causing a buffer overflow.
Moreover the JNI code for this was somewhat cryptic because it casted an
enum value to an int, then added 1 to compute the size. We now use
a switch statement to improve readability.
This issue was discovered (and the fix was verified) with the upcoming
Android port of the bloom demo.
We now never process mirroring or mipmaping with multithreading
it's just not worth it given the overhead of the jobsystem.
We also require 64 lines per job, below that, we only multithread per
face (6 threads). This should probably depends on the sample count,
but we don't have this facility yet.
Special case downsampling for mipmaping.
This alone improves performance by 2x for small cubemaps (e.g. 16x16).
This adds a utility function on IndirectLight populate the reflection
map from an environment at runtime. This performs some processing
similar to cmgen, albeit at a reduced quality.
In commit d955e73 we changed the default IBL from RGBM to RGB, but we
kept its internal format of RGBA8. Since the internal format is not
compatible with the data format, we see GL_INVALID_OPERATION during the
texture upload.
This is a single-pixel black texture, so the format does not really
matter, but this clears up a GL error seen on some platforms.
In commit d955e73 we changed the default IBL from RGBM to RGB, but we
kept its internal format of RGBA8. Since the internal format is not
compatible with the data format, we see GL_INVALID_OPERATION during the
texture upload.
This is a single-pixel black texture, so the format does not really
matter, but this clears up a GL error seen on some platforms.
- RGB_11_11_10 is exported in a RGBA PNG file where the 4 channels are
used as a uint32 storing a RGB_10_11_11_REV pixel.
We use the .rgb32f extension, and those PNG files contain garbage
when seen in a PNG viewer.
- This is now the default for the -x option.
- compressed KTX files don't encode RGBM, which means they can't
support HDR, unless an HDR compression scheme is used.
* Make CMake 3.10 the minimum version, add LTO option
* Install a newer CMake on Linux CI builds
* Update LLVM and Cmake on Windows CI
* Update build/windows/ci-common.bat
Co-Authored-By: Ben Doherty <benjdoherty15@gmail.com>
* Update formatting
* Apply suggestions from code review
* Update build/windows/ci-common.bat
* Update CMake
* Switch Android projects back to CMake 3.6
⚠️ breaks materials
There used to be a constraint that ibl cubemap needed to be
256x256. This constraint is now relaxed. IBL cubemaps can be any size.
We also add 16 float4 of padding to the frameUniform, which brings
its size to 1 KiB, the idea is to prevent more breakages in the
future.
For now this uses gltfio in the ubershader configuration in order
to avoid the filamat dependency. Note that we have not yet done a size
analysis of the `gltfio_core` library.
New Kotlin-based sample app is forthcoming.
NOTE: Should we expose Engine::getEntityManager() to help with issues
like this? e.g. it would allow gltfio to extract it from the engine
rather than consuming an additional argument.
This fixes an entity id collision that I saw when building gltfio into
its own DSO (e.g. on Android). Since it is a separate executable it has
its own EntityManager singleton. This id collision was causing unwanted
entities to be added to the scene.
No need for a proper library, this is just a common location to simplify
JNI bindings in other projects like filamat and gltfio.
There is no need to move the one Java source file (`NioUtils.java`)
since downstream libraries will have a dependency on Filament, and
FindClass should work fine.
This changes addresses issue #1307. We recently fixed the way we support arrays
of parameters to allow arrays of 1 element. Previously single elements (e.g. float)
were treated as an array of 1 element and the other way around. Unfortunately our
Java bindings relied on this behavior to set colors. This change simply directly
calls the float3 and float4 variants of setParameter() when setting a color.
Some projections matrices were incorrectly inverted.
This also fix#1281, fortunately, the incorrect matrix wasn't used
in that case.
Camera::inverseProjection only handles projection matrices it
created (as opposed to custom ones, which is what the shadowmap
code uses)
Arrays in unform buffers are stored in std140, i.e. they have an
alignment of float4. This wasn't taken into account when setting
arrays (other than mat3)
The bistro model has some UV-free primitives associated with textured
materials. This caused Filament to emit warnings like:
[entity=445, primitive @ 0] missing required attributes (0xb), declared=0x3
We now catch these in gltfio, which enables a friendlier warning so that
the artist can go make a fix:
Missing UV0 data in Bistro_Research_Exterior_Paris_Building_01_paris_building_01_bottom_4669
"mirror" was misleading, like it would apply a symmetry to the frame.
mirrorFrame() is just a blit from a swapchain to another, so it's a
copy.
The Java language API is kept for compatibility.
Instead of flushing the driver and command queue in RenderPass, we now
do that in the framegraph.
We flush the command queue after each pass -- which reduces memory
pressure on the command queue and improves parallel execution
with the backend thread. We flush the driver only after the last
pass -- maybe we could improve this in the future as the framegraph
gain more knowledge about what's going on.
GLVertexBuffer.gl.buffers is a std::array which is not
default-initialized, and createVertexBuffer only initializes the first
bufferCount fields of the array.
When destructing, destroyVertexBuffer iterated over all buffers to unset
bindings, but it was erroneously iterating over the entire array instead
of the initialized values. Update the loop to only iterate over known
initialized values.
This eliminates the flicker caused by triangle noise based dithering
when FXAA is turned on. This will require further investigation to
see if we can use triangle noise with FXAA without such artifacts.
If a client asks for more than 8 buffers in a VertexBuffer, they will
either crash (release) or hit an assert in OpenGLDriver (debug). It's
better to catch this earlier.
This was noticed while investigating #1256.
This allows us to skip the CPU-side vector-to-color conversion that
occured at the end, and makes the real-time visualization consistent
with the final visualization.
* Add screen and multiply blending modes
This change also fixes a sorting issue: different sorting modes
were sorted in different buckets which is incorrect. We want
to sort only by distance.
* Update release notes and Java API
* Fix build error
- it's now possible to use a level of a texture as an attachment of
a rendertarget in the framegraph, by simply setting the desired level
when specifying an attachment.
- for now, removed the (never used) feature where the framegraph could
resize a resource under-the-hood.
- when requesting the physical renderder target by calling
getRenderTarget(), we now must specify the same level that was used
when the rendertarget was created. This is not ideal, and we hope
to fix that in the future, but it'll require some serious internal
changes (and maybe API changes)
- useRenderTarget() has a helper for simple cases, make it even more
easy to use. It assumes a single color attachment w/ WRITE access,
which is a common case.
- update all useRenderTarget() access flags
This fixes a problem where the min lod of a texture would be set
incorrectly when first drawing into the base level (common case) and
then creating a mipmap chain from it using blits.
Because drawing into the texture doesn't set the base level, after the
blit, the min level would be set to 1 instead of 0.
In fact, there was no way to set the level of a texture by drawing into
it, the only ways were by blitting or uploading data.
This change updates the min/max LOD when a texture level is attached to
a rendertarget, regardless of whether we read or write -- assuming that
we will write to it. The problem is that at that stage we don't know
if we will read or write. That said, if the user attaches an uninitialized
level to read from it, who cares what really happens
Even when hex modifier is used, 'char' should be printed as characters,
this is particularly relevant with 0.
e.g. out << (char)0, should write a nul terminator, not "0".
Since we have a depth buffer, we might as well use it for depth-culling,
this automatically discards the skybox's fragments -- which we can
assume won't participate in SSAO.
- this means that we cannot share the depth pass between ssao and color
passes, so all this code is removed, which simplify things a lot.
- the depth pass code is moved into the ssao codepath since they're now
intimately linked.
- and finals ssao shader can't rely on frameUniform which is set up with
the main buffer's size (instead of 1/4 res).
This replaces the previous "curvature to roughness" method. Both are related
and rely on the screen space variance of geometric normals but this new
solution offers more control (the screen space variance and the clamping
threshold can be controlled).
It's now possible to set if a render target's attachment is accessed
for read and/or write -- instead of always being hardcoded to both.
We just add an "access" field to Attachment, which is still set to
RW by default, but can be set in useRenderTarget().
The access mode only affects building the graph -- in the end it's just
a regular render target.
There are now only 2 main commandTypeFlags, COLOR and DEPTH,
indicating if we need to generate respectively COLOR and DEPTH commands.
The command generation code, only has 3 implementations: DEPTH, COLOR and
DEPTH + COLOR.
We also add "options" flags that get passed along, used to control what
goes into the the depth pass -- this because sometimes we don't want
translucent or alpha masked objects. e.g. when rendering the shadow pass,
we want the DEPTH + shadow casters regardless of if they're translucent.
With this, we can fix a SSAO problem where alpha-masked objects where
not participating when the depth pre-pass was used. Now, we add those
objects to the DEPTH if SSAO is active and MSAA is not.
This adds some new functions to libimage for computing distance fields
and coordinate fields. This runs on the CPU but uses an efficient
algorithm. This will initially be leveraged by the baking pipeline to
dilate charts, but could be useful in other applications.
Filament references a few classes from native code and by reflections,
so when proguarding binaries we typically had to add an exception for
filament to make it run:
-keep class com.google.android.filament.** {*;}
In a compiled .dex file, the filament namespace takes about 120kb
(before compression), even if the classes aren't used.
To enable proguarding and stripping out unused filament classes,
introduce a UsedByNative and UsedByReflection annotation to explicitly
mark classes that need to be kept in the dex, so that the rest can be
potentially stripped out.
In my testing, this reduces the filament namespace in the .dex from
120kb->40kb, which translates to about 30kb apk size savings after
compression.
If A and B are equal keys, then hash(A) and hash(B) should be equal, but
xatlas was violating this constraint.
This bug was not present in Thekla's original code, it was introduced
later by the xatlas project.
Both SSAO and SAO are available, but currently only
SSAO can be used.
SAO is more correct and produces less "halos", but
SSAO is sometimes more pleasant.
Note that this doesn't implement all the SAO optimizations
yet.
* Add micro-shadowing based on ambient occlusion
* Prevent crash when IBL is turned off
* Apply micro-shadows to baked AO only
* Remove debug code
* Add opacity control
* Fix opacity term
* Switch to micro-shadowing from Chan 2018
The AO baking procedure consists of the following steps:
1. Flatten the glTF hierarchy.
2. Generate a single 2D parameterization for the entire scene.
3. Embree Pass 1: Create G-Buffer using the above UVs as vert positions.
4. Embree Pass 2: Cast rays from the positions embedded in the G-Buffer.
The `gltf_baker` tool is not ready for general use but already
produces reasonable results for certain well-formed models.
Normals reconstructed from derivatives at an edge are invalid and
Cause dark spots in the final AO. We try to detect this case and
Assume no AO, which could be wrong too, but looks better more often.
I don’t think it’ll have an impact on performance because the normals
for the whole quad should be wrong together.
AssetPipeline now has a path tracer and optionally uses embree. For now,
the path tracer only sends out visibility rays and generates a simple
hit-or-miss monochrome bitmap. It splits the render target into tiles
and invokes a JobSystem task for each tile.
Filament developers can optionally install embree using homebrew or a
debian package. This avoids bloating third_party and increasing our
build time. If embree is not installed, a friendly run-time error will
occur when attempting to invoke the rendering functionality in
AssetPipeline.
The AO code is not yet implemented, but this PR sets up the
infrastructure, API, and camera rays.
This feature consumes a flattened glTF asset and produces a glTF asset
with new topology and an additional set of UV coordinates suitable for
baking light maps.
I verified with a couple glTF models that the generated assets are
visually equivalent to the source assets, even though the topology and
scene hierarchy is different.
The actual light baking is not yet implemented, but this is a major step
towards that goal.
* Introduce AssetPipeline for performing glTF manipulations.
AssetPipeline offers a place for doing things like scene flattening,
transform baking, and optimization of glTF assets. These types of scene
manipulations will allow us to tackle lightmap baking in the upcoming
atlasgen tool.
This initial PR includes support for scene flattening, which is fairly
non-trivial. Support for parameterization via xatlas will be added in a
subsequent PR.
In a glTF asset, a single mesh can be referenced by several nodes, and
each reference can have a unique transform. AssetPipeline can flatten
the asset such that each instanced mesh has its own vertex data, and the
node transform gets baked into the vertex data.
Recall that gltfio is composed of two libraries: the core library (no
filamat) and the full library. This adds to the size of the full library
but leaves the core library as is.
* Fix various Windows build issues.
Platform implementations shouldn't depend on the concrete implementation
of the driver. e.g. PlatfromEGL.h shouldn't include OpenglDriver.h,
there is no reason for it.
Instead, we now have a {OpenGL|Vulkan|Metal}DriverFactory.h which is
only responsible to instantiate the correct concrete implementation
of the driver and Platform implementation only depend on that.
This effectively completely isolate the backend's header, which should
be completely private, and now is.
One benefit is that the backend's header needs to include
DriverAPI.inc which uses complex macros and this used to be expanded
multiple times, for each Platform. So this should help a bit with
build times.
We also mark *all* methods of all backends as "ALWAYS_INLINE inline",
which save quite a bit of code, without it, the compiler had to
instantiate each method twice. This saves 12KB on the final, stripped
libfilament-jni.so
We have a new TextureUsage::SAMPLEABLE flag, that is the default,
used for "regular" textures that can be sampled.
When this flag is not set, a RenderBuffer (in GL parlance) is
created instead.
This will be needed in an upcoming PR for creating RenderTarget more
explicitly.
The cgltf "base path" that gets passed to cgltf_load_buffers should
actually be the path to original glTF file, otherwise bin filepaths
are resolved incorrectly.
this is intended to help creating releases. this
file should be updated each time a commit is significant enough that it should be mentioned in
release notes.
when doing code reviews, reviewers should take this into account for approval.
"reverse resolve" is needed on desktop to emulate
EXT_multisampled_render_to_texture. However, it is not easily supported
on Metal or GLES. So for now we avoid relying on this.
This means that filament requirements are lower than what
EXT_multisampled_render_to_texture guarantees.
Essentially filament doesn't rely on being able to preserve the
content of a non-ms texture attached to a ms RenderTarget.
Also don't rely on being able to resolve+resize/move, which is
not supported in GLES.
there was a case where blitting from a multisample target with
a mix of multisample and non multisample attachments wouldn't work,
only the resolved non-multisample texture could be blitted.
this fix assumes that resolving doesn't damage the multisample buffer,
which is NOT TRUE on android with the EXT_multisampled_render_to_texture
extension. this will be fixed later.
Imported render target's discard flags (i.e. the imported flags)
were ignored, which means we were discarding the imported buffer
each time we were drawing into it, especially the 2nd time when
drawing the ImGUI.
This includes a small change to our custom material task because old
gradle passed only the contents of out-of-date directories, newer gradle
passes both the contents and the directory itself.
We would leak an FBO when using the same texture with multiple FBOs
and MSAA, this is because we have to allocate a sidecar FBO in this case
and we were doing so even if it was already existing.
Also store the sidecar fbo with the texture instead of the RenderTarget,
because it has nothing to do with the later. In fact we could have
several textures (e.g. color + depth) who both need a sidecar fbo,
so it can't be stored in the RenderTarget structure.
Also clean-up bindTexture().
It would happen when using a rendertarget without a color buffer and
a moveResource operation was set. We would incorrectly dereference the
color texture (which didn't exist).
We can now use for e.g. vec4<float> instead of float4, this is
useful for templated code. The existing solution was to reach
out to the math::detail::TVec<> class.
We were too aggressive removing vertices resulting from
the triangle/segment intersection test, that were not
contained in the frustum (this invariant should hold).
This happens because our triangle/segment intersection
is not watertight. Removing those vertices entirely would lead
to wrongly reduced light frustum.
Now that the lispsm code is more robust to these invalid vertices,
we can keep them. Most of the time they're harmless, because they're
close to the correct solution.
Compute the znear/zfar of the light space based on the bounding box
of each object in the scene instead of the bounding box of the union
of them. This is a bit more expensive, but we needs to run through
all of them anyways.
- switched the frustum/box intersection code to double. With large
scenes, we were getting very wrong intersection points (up to 1m off).
This doesn't seem to happen with doubles.
- reject points that end-up outside the frustum
- made LiSPSM code more robust against the problem above. When points
were falsely placed behind the near plane (due to bad intersections),
we could end-up with NaN (sqrt of negative numbers).
Also use new default bias parameters that seem to work better with
more scenes.
Renamed SAMPLING_HARD to SAMPLING_PCF_HARD because the GPU still
performs 4-taps PCF.
Metal only supports DEPTH24_STENCIL8, which is
what we're selecting for DEPTH24 (instead of
FLOAT32), this is closer to what the user asks
and doesn't use more memory.
Note that iOS doesn't support either.
The previous code worked only for directional lights and didn't handle
LISPSM correctly (the bias was scaled down).
We now apply the bias in world space, which works with all configurations.
Additionally the bias was always wrongly scaled by 2x.
The cost is 3 multiply-add.
This adds a condition variable to ensure that the wait occurs after the
flush.
Longer term we would like to not use fences to measure frame time and
instead use timing queries.
Fixes#1051.
(1) Merge two same-sized lists into a single map with struct values.
(2) Constify all the string-to-enum maps and move them into the
scope where they are used.
(3) Move a bunch of object methods into static free functions to
simplify the header and reduce code duplication.
(4) The PARAM_KEY_FOO string constants were referenced only once (except
in a few error messages) so replace them with string literals.
* Add new shading model to Filament for specularGlossiness.
This adds a shading model based on KHR_materials_pbrSpecularGlossiness.
The corollary gltfio change will be in an upcoming PR.
* Improve documentation for specular-glossiness
* MaterialInstance now has setMaskThreshold for convenience.
* Materials now support dynamic doubleSided property.
This does not change the format of material packages because they
already have both getDoubleSided() and getDoubleSidedSet().
The only way in which this change could impact existing applications is
that materials that explicity set doubleSided to "false" will now
respect the material's culling mode, rather than forcing it to NONE.
Fixes gltf_viewer with littlest_tokyo in ubershader mode.
Fixes#963.
* JNI for dynamic material properties.
* Add underscore prefix to internal material params.
* Remove un-needed mat info field.
We where treating a direction as a vector when projecting the camera's
forward vector. We never saw this bug before because we always used
<0,0,0> as the origin of the light space.
Now that we can pick an arbitrary light-space, we use the camera's
origin. Other choices are possible. But the camera origin is a nice
reference point.
Also simplify some code.
- "stable" mode disables all resolution optimizations that can affect
stability of the shadow map (e.g. lispsm, focusing)
- expose near/far hint + stable option to java
We were using the view frustum as a basis instead of the shadow
receivers volume which didn't give a good warping for the scene, we
were working around it by setting a virtual near plane dynamically.
Now that the warping frustum is tight, the virtual near plane is
no longer needed -- it's still needed for the user to adjust the
precision and the default is still 1m.
This is our first ImGui extension, it draws a draggable 3D arrow for
manipulating a unit vector. This is especially useful for tweaking the
light direction.
this is mostly simplifying and playing nicer with the framegraph, in
particular, now the framegraph computes the discard and clear flags
for the color pass.
the next step will be to move the shadow pass to the framegraph.
* Add postLightingColor property to materials
This property can be used to modify the color computed in the lighting
passes of the materials. That color is blended with the computed color
according to the postLightingBlending option (add, transparent or opaque).
* Remove test
* Update docs
* Address code review comment
* Switch postLightingColor default blend mode to transparent
One of the recent releases of emsdk moved its GL-related utility methods
into an object called GL, previously it exposed them directly.
This change also makes it so that we create the WebGL 2.0 context
and register it with emscripten, rather than the other way around.
Note that our CI does "emsdk activate latest", not sure when this broke
exactly.
* Removed STL headers from filameshio/MeshReader.h modified the samples to work the same, and made an effort to remedy the jsbindings although I'm not experienced with them.
* Fixed assignment operators for MaterialRegistry
* Fixed formating for MeshReader Material Registry
* Forgot one format
* Forgot another format
This is just a cleanup and does not change any behavior. The old code
was a little strange because we'd generate code designed for OpenGL but
we'd pass VULKAN to the code generator. This was a little white lie that
really meant: "I will need SPIRV (for optimization purposes only)"
This fixes two issues related to the Vulkan backend, one being a build
issue and the other being a run-time issue:
(1) Compile-Time Issue
To prevent accidental introduction of padding into hashed structures,
the Vulkan backend was static-asserting the size of the hash input. I
think it's fine to simply use a pragma pack instead.
(2) Run-Time Issue
SibGenerator was erroneuously using BindingPoints::COUNT instead of
UNIFORM_BINDING_COUNT for determining the first sampler binding index.
(Hopefully this logic will go away after some upcoming Vulkan cleanup.)
Since SibGenerator does not include Program, this moves the uniform and
sampler counts into EngineEnums, which might be a good place anyway
since they are ideally "config" constants.
There is a new static method that can be used by derived classes to
instantiate an OpenGLDriver.
This is to support existing clients that use their own implementation
of OpenGLPlatform with filament's OpenGLDriver implementation.
There are two changes involved here:
1) Recreate (do not recycle) the submission fences at every frame.
2) Add shared ownership semantics to existing fences to allow DriverAPI
clients to "own" fences.
The first change was motivated by FrameSkipper, which might have a
fence list that is longer than the number of swap chain contexts.
The second change was implemented simply by creating a tiny wrapper
struct for VkFence with a proper constructor and destructor, then
leveraging shared_ptr.
There are a couple reasons for this change. First of all, creating a
Vulkan fence outside of beginFrame / endFrame is not ideal because
the backend does not know yet which command buffer will be chosen
during swap chain acquisition.
Secondly, the Renderer currently calls endFrame in this order:
frameInfoManager.endFrame
mFrameSkipper.endFrame
driver.endFrame
However the beginFrame calls were ordered like this:
frameInfoManager.beginFrame
driver.beginFrame
mFrameSkipper.beginFrame
This change makes it such that the beginFrame calls have the reverse
ordering of the endFrame calls, which is less surprising.
I did a poor man's sanity check by running textured-object on a Pixel 2,
(which enables dynamic resolution) and hacking PostProcessManager to
make it visually obvious if anything were amiss.
This is mostly about moving constant from EngineEnums.h to
the backend, either in Program.h or DriverEnums.h
The goal is that libbackend doesn't depend on EngineEnums.h
OpenGLPlatform, VulkanPlatform and MetalPlatfrom are no longer public
classes, they never should have been.
This will break code using those, the solution is simply to copy the
header locally.
- get rid of type aliases in Driver:: we use the driver:: version instead.
- Only use the Handle<> aliases in DriverAPI.inc -- they exist only
because of the macro hackery we have to do.
- move all public-ish types of libbackend into the 'driver' namespace
(later to be renamed to 'backend')
This removes a dependency on DriverBase.h of libfilament.a
This also means that Platform::create() and createDriver() are now
public APIs of libbackend -- not reserved to FEngine anymore.
In this first step, we just "blindly" move everything under src/driver
to a new library libbackend.a. And all headers are moved under
private/backend.
Note that "driver" is renamed "backend", but namespaces are unchanged for now.
Later we'll have to untangle the actual private headers from public
ones and ideally not have any private headers.
It's more logical to do it this way in the API. Also, MSAA needs an
intermediate buffer (currently), so enabling MSAA in the "UI" view
wouldn't do what's expected -- it would prevent the "UI" to be blended
properly (again, currently).
This introduces a reference counting mechanism to allow us to defer
destruction of Vulkan resources to the correct time, rather than doing
an aggressive flush-and-wait before every vkDestroy*().
This also preps for removal of the "pending work" queues of
std::function, in favor of using the new Vulkan command buffer
designated for extra-frame activities such as uploads, blits, and layout
transitions.
- the IGNORE_VIEWPORT flag is gone. It wasn't actually needed and what
it was doing was ambiguous.
- removed the backend viewport() API which wasn't actually needed.
- beginRenderPass() now ALWAYS sets the viewport and scissor but
doesn't necessarily clears honoring the scissor (based on the
IGNORE_SCISSOR flag).
- the GLES backend now just sets the scissor when it needs it, as opposed
to always trying to keep it set. we now rely on state tracking to
de-dup the gl calls.
Because with OpenGL ES backends, it's not allowed
to blit with a linear filter when depth/stencil is used, we need to
expose the filtering option.
In the GLES backend if the linear filter is selected and depth/stencil
is selected, filtering is downgraded to nearest silently.
It's now possible to enable/disable tone-mapping, fxaa, msaa and
dynamic resolution independently.
A new set/getToneMapping() method is added to View.
It's still possible to disable *all* these post-processing effects
together using setPostProcessing(). This is currently needed when
rendering a transparent view (such as UI) on top of another view.
This limitation might be addressed in the future.
This fixes#621
when a resource that is also an attachment of a rendertarget is aliased
(with moveResource) with a resource from an imported rendertarget, the later
wouldn't always replace the former as expected.
Filamat public headers were including a private header. This PR fixes
this problem. It also forces filamat to always be compiled to avoid
breaking filamat without noticing. The flag `-l` is not available
anymore in build.sh as a result.
Eventually the framefraph will deduce some of these things automatically,
but for now, the texture format must be specified.
Also added a couple error checks in the gl backend.
when blitting from a multisample render target, we must use the
resolved buffer (b/c resolve is always done in endRenderPass), currently
we were basically resolving twice.
Some GPU seem to loose the content of UBOs for draw calls emitted
before a glFlush followed by more draw calls.
On those GPUs, we just never call glFlush, which could result in
reduced parallelism between the cpu and gpu.
The new gltf_viewer app has an optional zero-arguments mode whereby it
loads a resgen-embedded binary model, which is useful for quick
sanity testing. If you don't specify an IBL, it loads a compressed
version of the pillars IBL.
no need to hide the implementation anymore, since the whole thing
is internal and doesn't appear in public headers.
this saves a dynamic allocation when unflattening materials.
We will need 6 pre-compiled materials (lit vs nonlit and the 3 blend
modes). This uses CMake's "configure_file" functionality to generate 6
mat files, then invokes matc on each one. They are then combined using
resgen.
- getCameraComponent(Entity) retrieves a Camera component from an entity
- destroyCameraComponent(Entity) destroys just the camera component
attached to an entity.
destroyCamera() are now deprecated because the API is confusing, it's
not immediately clear that it's destroying all component + the entity
itself.
Node: We don't add the corresponding Java APIs yet because there is no
easy way to guarantee they're safe without making sure that
getCameraComponent() will always return the same instance (which it
wouldn't currently).
This makes it easy to draw a transformed box around each renderable for
diagnostic purposes. The API is similar to Animator in that it is
exposed through FilamentAsset but is created lazily and is implementated
outside of FilamentAsset.
gltfio computes two types of bounding boxes: one for renderables (used
for frustum culling) and one for the overall asset (used for
positioning the camera or asset).
Both of these are based on the min+max attributes in the glTF file, but
the asset-level box was incorrect because only two corners of the
transformed AABB were considered.
This CL also adds optional computation of bounding boxes that crawls
through the vertex positions. This is useful when diagnosing potential
issues with the asset's min+max info.
These enhancements are motivated by a culling issue seen with the voxel
Cathedral on sketchfab.
Instead of passing SamplerInterfaceBlocks and a SamplerBindingMap to
Program, we now set a 'sampler group' per binding point:
Program::addSamplerGroup(...)
A sampler group here consists of a list of N 'Sampler' and a 'Sampler'
is just a unique name (unifrom name in the shader) and binding point in
the shader.
That's all the driver layer needs.
With this change we get rid of the code that re-created the uniform
names in the driver -- this should never have been done there. And we
also remove the hash-map lookups in vulkan and metal drivers.
This fixes#935
SamplerBindingMap was always adding the post-process samplers to the
map -- but matc doesn't generate those. This led the vulkan backend
to believe there was a post-process sampler bound, when there wasn't.
This is also technically a bug in the Vulkan backend because it should
have used the SamplerInterfaceBlock to determine which shaders are
actually used instead of blindly going through the whole list and
trusting SamplerBindingMap.
The fix is kind of a hack, but the whole SamplerBindingMap is kind of a
hack anyways.
In my previous NaN-related commit, I added a conditional similar to the
one seen in glMatrix, but this was insufficient for the interpolation
seen in a glTF skinning test because a divide-by-zero was occuring later
in the function. This commit simply adds back the previous protection.
It's only used to get the size of the SamplerGroup.
Actually, Engine also uses the post-process Sib to create the
post-process material, but this should go away when we have
material domains -- so pretend it's not there.
Program::shader() was taking a string before which didn't make sense
for spirv. Now it's just a blob, in the case of GL/Metal, the blob
must be a null terminated c-string, and the size must include the
terminating null character.
This fixes an out-of-bound access in ShaderBuilder::getShader() (which
doesn't exist anymore), because it was creating a CString passing
a size that included the null terminating char, which is not was CString
expects. CString can now assert() in that case.
driver::Program now uses a std::vector<> for storage, which we should
fix at some point (b/c it's a public header). CString was not suited to
store binary blobs.
* Add build command for Markdeep files
build.sh -w can now be used to "rasterize" Markdeep .md.html files
to regular, static .html files. These files load faster and do not
suffer from an initial flash of uninitialized content.
This new command requires node, npm and nx to run puppeteer to
"rasterize" the Markdeep documents. This should eventually be
integrated in the actual build system to automatically re-generate
the HTML files when the Markdeep documents are edited.
* Remove unnecessary .gitignore file
* Change constant names for JS docs
- EngineEnums.h is not a private headers as it contained mostly private
stuff
- MaterialEnums.h is still public, but now only contains public stuff.
Private parts were moved to MaterialEnums.h or MaterialBuilder.h
- And finally SamplerBinderMap is moved under private/ as well, since
it's certainly not a public API.
With this change, the public headers of filabridge become more reasonable
and limited.
This is because 'from' is now written to, so we should invalidate it
just like for a regular write.
moveResource() now asserts when using an invalid handle. The caller can
use isValid() to check the handle if desired.
when we compute the depth range of the shadow map, if znear is behind
zfar, it just means we don't have any shadow caster in front of
a receiver, and we can just bail out without shadowing -- as opposed
to asserting.
This is effectively moving all shader computations to view space,
improving floating-point precision in the shaders, by staying
around zero where fp precision is highest. This also ensures that
when the camera is very far from the origin, objects are still
rendered and lit properly.
- Add support for CUBICSPLINE and STEP interpolation methods.
- Use cgltf_accessor_read_float() instead of manually unpacking values.
- Fix potential NaN in decomposeMatrix.
- Reduce malloc churn by stashing the vector of bone matrices.
filaflat only had on header dependency on filabridge (DriverEnums.h)
and only needed two small enum types.
In fact, I don't think it was right for filaflat to assume any
particular value for these fields -- this is the responsibility of the
callers.
This is our new mobile-friendly and web-friendly library for loading
glTF assets. It is still a work in progress, but already capable of
loading many conformance models, including those with animation,
skinning, and a couple of extensions (nonlit and texture transforms).
Next week we will add a sample app demonstrating its usage.
With this change, filaflat looses almost all its dependencies on
filabridge (only needs DriverEnums.h) and becomes only a parsing
library that doesn't know anything about materials.
It still knows about "shaders" as blobs of text or data (spirv).
Filaflat itself is used by matinfo and filament.
We now expose things like
BlobDictionary: dictionary content
MaterialChunk: construct a material from the BlobDictionary
SpirvDictionaryReader: reads a spirv dictionary
TextDictionaryReader: reads an ascii dictionary
All these classes are generic enough and don't have any outside
dependencies.
The only remaining class which has outside dependencies is
MaterialParser, which will be eliminated soon.
This is used by our upcoming gltfio library and is the lightest-weight
glTF reader that we know of. In fact it does not do much other than
parse the JSON and provide C structures for the data.
The default constructor of the Viewport class left the view properties in an uninitialized state that could lead to an undeterministic behavior in the later stages during rendering.
In our case, the issue manifested in the Froxelizer class in the setViewport() method that was flaky because sometimes the old viewport in the Froxelizer class (mViewport) was equal to the newly set viewport which caused the mDirtyFlags to not be updated. This then resulted in a crash because mPlanesX and mPlanesY were not allocated in the update() function even though they were used.
* Rename MetalImpl to MetalContext and move to separate header
* Remove m prefix from MetalContext variables
* Refactor out acquireDrawable method
* mCommandQueue -> commandQueue
This fixes#887. this bug existed since forever, when setting the
samplers on a new material instance from the default material
instance, we were losing the dirty bits (i.e. they were copied),
and so the newly initialized buffer would never be comited.
This adds a setSamplers() methods which does exactly that, and for
symmetry (and more efficiently) we also add setUniforms() to
UniformBuffer.
- UniformBuffer::toBufferDescriptor() now cleans the dirty flags
- SamplerBuffer move ctor and operator now clean the dirty flags of the
moved (source) buffer.
- SamplerBuffer::toCommandStream() can be used to more efficiently copy
a SamplerBuffer into the command stream -- this saves a copy.
- simplified SamplerBuffer's copy and move ctor/operator
- added a few constexpr here and there
This moves our existing VertexBuffer utility into a new "geometry"
library and adds new functionality for computing tangents based on UV's.
The UV-based method comes from Eric Lengyel.
We considered mikktspace (which thankfully has a zlib-style license) but
it would require re-indexing via meshoptimizer and is therefore a bit
heavyweight.
The new library has no dependencies and will add only 7 KB to Filament's
Android aar file.
Fixes#858 and preps for #528.
The move ctor wasn't implemented properly. We actually fix this by
using a std::vector<> instead of a raw allocation for storing entries.
This std::vector<> is never reallocated.
* Android standalone toolchains are not longer necessary
The latest NDK (19) contains ABI/API level specific command line
tools making standalone toolchains unnecessary. This change adapts
to the new model which greatly simplifies the build script and
ensures the latest version of the tools is being used.
Note that this requires a fairly recent version of CMake which fixes
a bug related to ranlib. This change was tested with CMake 3.13
(CMake 3.7 does not work).
* Modify CI build script to fetch recent CMake
* Remove dependency on standalone toolchains in Windows README
* Use correct CMake path
* Update NDK to latest
* Only download CMake and NDK for Android builds
* Add version constant for ninja
* Make output more quiet
It's now possible to create a multisample FBO with a non-multisample
texture attachment. In this case, the drive is responsible for
automatically resolving the multisample buffer into the texture on
endRenderPass().
This allows us to avoid doing a "resolve blit" on the client side, but
more importantly, it allows the driver to do this efficiently,
especially on tilers.
The semantic of this operation is the same than with
EXT_multisampled_render_to_texture. i.e. the multisample buffer is
lost after resolve. For GL/GLES drivers if
EXT_multisampled_render_to_texture is not available this behavior
is emulated with a renderbuffer + blit.
This CL also fixes the creation of attachments to a face of a cubemap.
vertex shader interpolants are interpolated at pixel centers by the GPU,
but we were doing our own "pixel-center" adjustment, so we ended-up with
"vertex_uv" at a pixel corner instead of center.
with this change, the vertex shader always compute vertex_uv in
fractional texels and the conversion to texture coordinates is done
in the fxaa code.
The half-pixel adjustment is removed.
This leads to sharper looking images because in addition to shifting
everything by 0.5 pixels, this was essentially applying a box-filter
to the whole picture -- kind of like taking 1 mip level down.
This is one of those CMake gotchas, we should always use
CMAKE_CURRENT_SOURCE_DIR instead of CMAKE_SOURCE_DIR to allow
Filament to exist as a subproject.
In particular, this was causing the following build error when trying to
build Filament as a nested project.
combine-static-libs.sh: No such file or directory
Fixes#861.
By removing the Fresnel term (often ommitted from fabric/cloth BRDFs)
we can store the DG term for the cloth BRDF in the 3rd channel of the
existing DFG LUT.
Assimp's CalcTangentSpace deviates from de facto glTF 2.0 so we were
compensating for this with an unconditional fixup in MeshAssimp. However
the fixup should apply only when CalcTangentSpace is active, i.e. when
the model is missing tangents.
This makes it so that NormalTangentMirrorTest (has tangents) and
NormalTangentTest (needs tangents) both look reasonable.
I also noticed that MeshAssimp was inexplicably applying
aiProcess_CalcTangentSpace twice: once as a flag, and once as a
post-process. I removed the latter.
This will be fixed in the upcoming cgltf-based loader, which will
use our officially-sanctioned utility method in VertexBuffer.
See #528
we never rely (or should rely) on the fact that glBinderBufferRange()
also sets the generic binding, so we don't need to check for that when
calling glBindBufferRange().
This helps a little bit reducing the numbers of GL calls, especially
when several consecutive draw calls use the same material instance.
synchronous driver calls are split in 2 calls, respectively:
fooS() and fooR() instead of fooSynchronous() and foo().
This is a tiny step towards decoupling drivers from the
renderstream, which is a pipedream of mine.
Material archives already contain two version chunks (post process and
normal) but the renderer was ignoring these. The change makes it so that
matc writes a new MaterialEnums value into these chunks, and the engine
panics when receiving a material version that it does not expect.
This also adds a --version option to matc. No changes were necessary
to matinfo because it already prints out these values.
Fixes#796.
It looks like out static libc++abi that we use on linux needs
pthread, even if the exe doesn't use it.
Adding libutils to this test fixes the build on my local linux machine.
The real fix is probably something else, bug I don't quite
understand these shenanigans.
the texture's max level wasn't set properly when uploading
data for level 0 (it was for other levels).
this would cause uninitialized levels to be accessed by the GPU.
This is an efficient method that allows clients to add a slew of
entities to the scene. This is particularly useful for the upcoming
gltfio library, which is agnostic of the Scene and exposes a flat
list of entities.
- when possible we resize the attachments
- we also round to 32 pixels to take avantage of
pools the driver may have.
- when attachment can't be resized and don't have
the same size, we do best effort -- i.e. resize
the ones that we can.
Resources are now single textures (generally buffers in the future),
but no longer a render target + a set of texture.
Instead, render target need to be declared and are associated to a pass.
The bug was reproduced and the fix was verified by copying the following
code snippet into one of our Android samples:
val norm = floatArrayOf(1.0f, 0.0f, 0.0f)
val tang = floatArrayOf(0.0f, 1.0f, 0.0f, 1.0f)
val expected = floatArrayOf(0.5f, 0.5f, 0.5f, 0.5f)
val resultBuffer = FloatBuffer.allocate(4)
val qtc = VertexBuffer.QuatTangentContext()
qtc.quatCount = 1
qtc.quatType = VertexBuffer.QuatType.FLOAT4
qtc.outBuffer = resultBuffer
qtc.normals = FloatBuffer.wrap(norm)
qtc.tangents = FloatBuffer.wrap(tang)
VertexBuffer.populateTangentQuaternions(qtc)
Log.e("Filament", "${expected[0]} == ${resultBuffer[0]}")
Fixes#695.
The `./` and file separator in the executable path prevented the program from running. The other changes are just cleanup for conformity. This is the last of the Windows doc changes as far as I can tell.
This class will not extend well to glTF so this cordons it off into the
filamesh namespace, which is an already-existing namespace that we use
for the things related to the filamesh file format.
For glTF we might create a new library with its own MeshReader so
this will mitigate confusion.
we could crash by dereferencing something that's
not a pointer when blitting to a rendertarget not
backed by a texture (i.e. renderbuffer).
also there was a case where we couldn't disambiguate
between the two cases.
This fixes an INVALID_OPERATION at draw call time with skinned
renderables. We do not see this error with Adreno drivers, but we saw it
with WebGL, and technically our usage was not spec compliant.
In the public docs and materials API, Filament "variables" are custom
interpolants (outputs of VS, inputs of FS). However we internally used
"variables" to also refer to built-in VS inputs.
CodeGenerator had a generateVariable method and a generateVariables
method, which did something completely different. :)
The vk_imgui sample regressed in December or so, after some changes in
how Filament manages uniform buffers. This commit makes the Vulkan
driver more consistent with the GL driver, which does a check for
zero-sized buffers.
This reverts a JobSystem optimization that attempted to avoid signaling
a condition when there was no waiters. Unfortunately, there was a
race that caused the the signaling thread to miss that the waiter flag
was set, thus not signaling.
We were stashing the GL format but not the Filament format.
This simplifies VulkanTexture and will allow us to implement a very
simple mipmap generator in DriverBase.
Motivated by #749.
Amazingly, the size field in PixelBufferDescriptor was often totally
incorrect for Java-based clients. The reason we did not notice: OpenGL
often consumes a pointer to image data without consuming a byte count
(e.g. glTexImage2D).
OpenGL infers size from dimensions + format, but Vulkan does not. This
caused texture corruption with Vulkan on Android.
This fix follows a pattern used in other places such as
FRenderer::readPixels.
Gradle creates a hidden .externalNativeBuild folder when issuing CMake
for the first time. This folder contains cached command line parameters
that get passed to CMake, and these can become stale when switching
between "normal" Android builds and Vulkan-enabled Android builds, which
leads to frustrating build errors.
- validate that a pass actually uses a resource when requesting the
concrete (Driver) handle.
- introduce a "blit" usage for a resource, which indicates that a
resource will be used as the source of a blit operation. This is
unfortunatelly needed because blit operations work on rendertargets,
not textures for the source.
- de-dup read/writes to the same resource from the same pass
- also, when reading & writing into the same resource from the same pass,
always order the read before the write, i.e.:
out = builder.write(r);
in = builder.read(out);
is equivalent to:
in = builder.read(r);
out = builder.write(in);
note that the following is still not allowed:
out = builder.write(r);
in = builder.read(r);
this is never valid, since it's reading from a resource that has
been written to.
- Make FrameGraphResource class attributes private and add
comparison operators (so they could be sorted and compared).
The engine tries to be smart by using a single vertex shader when
rendering unskinned, non-alpha masked, non-customized materials.
This leads to a lot of issues when laying down the depth prepass.
This change simply gets rid of this optimization (which wasn't
properly profiled anyway). Correctness is more important.
Fixes#645
When clients deleted renderables that referred to index buffers that
were still active, it was possible for our shadow ELEMENT_ARRAY_BUFFER
binding to get out of sync with the actual binding.
It is somewhat amazing that this has never caused issues before. Perhaps
it is rare for clients to "recycle" index buffers across multiple
renderable lifetimes.
This fixes#718.
The following type bindings are now complete:
- RenderableManager
- RenderableManager$Builder
- RenderableManager$Bone
- TransformManager
- Box, Camera, Frustum
* Fix the Android filamesh file loader
The loader was not updated to support the SNORM16 format now sometimes
used to encode UV sets in filamesh files.
Fixes#708
* Update android/samples/image-based-lighting/app/src/main/java/com/google/android/filament/ibl/MeshLoader.kt
- baseColorFactor.a was not taken into account
- Some glTF files do not set `doubleSided` properly, so here we assume
that non-opaque materials are double-sided. We may need to revisit
this decision later...
We still do not compile the Vulkan backend for Android by default, this
simply makes it possible to use the samples on Vulkan with a one-line
change, which is useful for testing purposes.
This change also makes it so that the materials used for the samples
include SPIR-V. This makes them fatter but they are merely samples.
I still consider Vulkan on Android to be experimental, there are some
features that need to be implemented.
* Add specular anti-aliasing properties to materials
curvatureToRoughness
limitOverInterpolation
These techiques were supposed to be enabled by default on
desktop but it turns out they were broken. They must now
be enabled manually on each material instead (and work on
mobile).
* Update docs/Materials.md.html
This is a more complex test than suzanne because it has multiple
materials and exercises the named materials functionality in
loadFilamesh.
This also exercises our glTF-to-Filamesh pipeline at build time.
See issue #663
filamesh requires UV's but some glTF test models, like CesiumMilkTruck,
do not provide UV's on nonlit parts (e.g. the truck windows). This makes
it so that these assets can be converted to filamesh somewhat more
gracefully.
Background: with the Vulkan backend, RGB8 textures do
not work (at least not on my hadrware). This makes me unable to run some
examples, because they use normal maps in RGB8 format.
It appears that the following commit addresses the problem by adding a
special command line option to mipgen:
8dda07bf2c
However, processing normal maps with this option does not work: certain
assertions in the image library fail.
This PR changes these functions in the image library to handle 4-channel
images instead of failing.
* Improves linear to s/rgb
Adds rounding to nearest whole integer, supports copying over an alpha channel for linear to srgb conversion. Code would previously incorrectly apply sRGB conversion to alpha.
* reformatting previous change
Fixes a header usage problem for MSVC, which complains about StaticString not having a constexpr constructor thus making the "make" method not constexpr.
* Fix FXAA computations in mediump
UV coordinates computed in highp should be passed to the FXAA function
in highp as well. This change also fixes a potential division by 0 which
was causing dir1 to have components set to inifinity, thus breaking the
texture sampling calls below. We fix this with an early exit when a
potential division by 0 is detected. The original code contained a bias
to try to avoid this problem but that bias was not always enough. It
was frequent in mediump to cancel out the bias.
* Update shaders/src/fxaa.fs
Co-Authored-By: romainguy <romainguy@curious-creature.com>
- only signal waitAndRelease() when the corresponding job finishes and
only if there is waitAndRelease() active -- instead of signaling
every time a job ends.
- don't surrender time slice when attempting to steal a job and it fails
as long as some queue has jobs.
- check that we have to wait, because taking the lock
- add a benchmark
This change more than doubles the amount of jobs we can handle per
second (~965,000 jobs/s on Pixel3)
We don't need libfilamat/spirv*/glslang for now. They greatly
reduce the time it takes to build our Android targets. We
may want to create a separate CI profile for filamat actually.
* Improve rendering to TextureView
UiHelper wasn't calling the resize callback at init time when attaching
to a TextureView, but it was for a SurfaceView. This makes both code
paths consistent and fixes the standard samples if they are modified to
render to a TextureView.
This change also adds a new sample app that shows how to render into
a TextureView.
* Suppress warning
* Suppress another warning
JobSystem::waitAndRelease used to spin to wait for the job to finish,
usually this wasn't a problem because the spinning thread was
able to handle other jobs. However, in cases where no job was
available it would actually spin in burn cpu cycles.
we now use a (separate) condition variable to handle that case.
In a lot of case the StaticString hash can be computed a compile time,
so we now take advantage of that.
Removed StaticString(const char*) ctor, and replaced it with a
StaticString::make() method.
Fixed a couple wrong uses of the old StaticString(const char*) ctor.
We simply don't emit unwind tables, which are not needed anyways since
we're compiling without exceptions. the combined saving for all four
targets we support is about 120K.
This seems to improve .aar's compression, for a total gain of 152 KiB.
We also disable stack-protector in the jni code, since it wasn't
enabled in libfilament.a anyways. However, we now compile all debug
builds with -fstack-protector
- make Profiler::readCounters() not inline as it didn't need to be,
it's not performance critical and it's sufficiently large.
- don't inline hasExtensions(), same reason.
This is similar to its WebGL and Android counterparts, we simply did not
have a version for desktop. This uses resgen to package the model's
textures (albedo, normal, roughness, metallic, ao) into a library that
is linked only to this sample.
This is a good test because it applies multiple textures to the model.
Moreover Aaron was asking me for a C++ example that uses compressed
textures.
For now this selects the OpenGL backend. We can change it to use Vulkan
after we add support for 3-band formats to VulkanDriver.
* Turn on shaders optimization by default
Release builds of Filament only work well with optimize shaders,
turning optimizations on by default will help avoid mismatches.
This change also adds -g to disable all optimizations, for debug
builds.
* Use -g on debug builds
* Use -g on debug builds
* Update tutorial_redball.md to remove matc's -O
* Update tutorial_suzanne.md to remove matc's -O
* Use -g in debug builds
This calculates the modulo of the user time by a given value, using
the high precision user time. This is useful for animations without
having to worry about resetting the time.
the code was structured so light culling and renderable culling could
be done in parallel, but this wasn't implemented.
Clean-up some methods to turn them to static and run light culling
in parallel with renderable culling.
We used to only wake up a job-queue if there was already some jobs
running, the idea was that the current thread would handle the new job
as soon as calling wait(). However, there is no guarantee that wait()
will be called anytime soon.
cv.signal() is not very expensive on Android/Linux, as we're using
a custom implementation.
THIS CHANGE BREAKS MATERIALS.
This adds getUserTime() in shaders/materials, which returns the time
in second since Renderer::resetUserTime() was called.
Two values are provided, the time in second encoded as a float and
the difference between that and the double value, which together allows
to perform high precision time computation when needed.
This change allows longer running animations in materials. Using only
the float value, give millisecond resolution for more than 4h.
The dimensions passed into the VkBuffer-to-VkImage copy utility
specify a subregion for the copy, not the dimensions of the base level.
We were handling mipmapped cubemaps correctly, but mipmapped 2D images
were incorrect.
* Enable optimization passes on materials with external samplers
Because external samplers are not properly supported by SPIRV and
associated library (spirv-cross and spirv-tools) we currently disable
all optimizations when we encounter a material with external samplers.
This however causes issues on some misbehaved drivers (not running
the optimizations has a side effect which causes a crash). To enable
the optimization pass we simply rely on the Vulkan codegen target to
substitute samplerExternal with sampler2D. We then analyze the output
GLSL (post-optimization) and revert the relevants sampler2D declarations
to samplerExternal declarations.
This fixup only occurs after optimization and for mobile targets and
if external samplers were declared.
* Address review comments
* Add View::setFrontFaceWindingInverted() API
This API can be used to flip all meshes in a render pass
inside out. This is useful for mirrored rendering.
This change also disables face culling on the default skybox
renderable. Since it is unlit, there is no downside to this
and the mesh being in the device vertex domain it can never
be backfacing unless front face winding is inverted.
* Track face winding state in Vulkan
- use the exact required size for bone data instead of always the max
of 256 bones. This also reduces the amount of data to update and
copy into the command stream.
- also get rid of the "reuse component" optimization, which is less
needed now that renderables don't have their own transform UBO.
* grouped MeshAssimp arguments into struct
* added snormuv optimization to MeshAssimp and changed snormuv optimization range from [0, 1] to [-1, 1] in filamesh
This restores the canvas-based decoding method that was removed in #214,
but only for JPEG images. We continue to decode PNG images in C because
canvas-decoding mucks with alpha and prevents us from reading 16-bit
PNG.
Note that the WebGL build uses filameshio, but Android does not. Our
Android samples therefore do not yet understand the compressed format.
For web, I measured the before / after:
```
BEFORE: filament.wasm = 505796, suzanne.filamesh = 521476
AFTER: filament.wasm = 510915, suzanne.filamesh = 333489
```
Issue #558
This also adds it as a dependency to filameshio. This does not seem to
increase the size of the WebGL build even though filameshio is a
dependency, perhaps because we are not using it yet.
When cmgen creates ktx files, it creates a pair: one with an _ibl suffix
and one with _skybox. This convention is now honored by FilamentApp.
Note that we already have several KTX environments in the repo, so you
can clone a fresh repo and do:
gltf_viewer --ibl={FILAMENT}/docs/webgl/pillars_2k DamagedHelmet.gltf
Note that we have several hundred files in samples/envs, we should
consider replacing those or copying the environments in docs/webgl
(which git would internally de-dup, due to content hashing).
(1)
Generating the C file (only used for WebAssembly) causes slowness in the
build so this makes it into an option. Also, we were flushing too often,
which made it even slower.
(2)
Using "static" in a header was causing symbol duplication.
build.sh -p all builds everything which may be too much. -p now
accepts a list of platforms. For instance to build Android and
desktop:
./build.sh -p android,desktop release
View::setRenderQuality gives the ability to control the rendering quality
of a given view. In particular this allows the app to lower the quality
of the HDR color buffer by using R11G11B10F instead of RGB(A)16F.
This shows how resgen can be used for mesh data. It also removes the
MeshAssimp dependency from samples that were meant to be small and
self-contained.
This adds a couple optional features:
1) Preserve file extensions when generating symbols.
This is useful to distinguish foo.vs from foo.fs
2) Append null characters to data blobs.
Useful when treating FOO_DATA as a C string.
We started to write our own implementation of mikktspace, but it
required an unindexed mesh for input. This was awkward because assimp is
already applying a pipeline of operations that includes tangent
generation and indexing. It felt reduandant to add our own pipeline on
top of that (unindexing => tangentgen => reindexing).
Since assimp's CalcTangentsProcess method is already producing
tangents that follow the orientation implied by texture coordinates,
this simply needs to be tweaked to match glTF. (flip the bitangent)
Also fixed a bug for the case where models have neither UV's nor
tangents, where we were calling norm instead of normalize. :)
An assert checking invariants would sometime trigger, the problem
was a logic error that would be exposed by a race when running out
of space in the list.
The root of the problem is that in one place we were not remapping the
-1 offset to nullptr, storing a pointer violating our invariants.
Also added more asserts!!!
FADE is just a variant of TRANSPARENT that only affects shading.
This change introduces the "render blending mode" which is the
blending mode that must be used when generating the render keys.
The error message could say "need 0x2 but contains 0x2" which is still
confusing. Now that we're printing the actual required shader model
in English, we can simply say:
The material 'foobar' was not built for desktop.
Compiled material contains shader models 0x2.
* Revert "Rollback MeshAssimp enhancements."
This reverts commit b3dce967eb.
* Re-enable glTF support
* Start looking for texture ids at 1, not 0
* Detect if the importer is glTF
* glTF and regular materials both work
This tool can be used to replace inc files for built-in materials. The
inc files are unfriendly to IDE's and do not extend to non-material
resource types such as baked texture data.
The tool aggregates a sequence of binary blobs, each of which becomes a
"resource" whose id is the basename of the input file. It produces the
following set of files:
resources.h ......... declares sizes and offsets for each resource
resources.S ......... small assembly file with incbin directive
resources.apple.S ... ditto but with different rodata name
resources.bin ....... the aggregated binary blob
resources.c ......... large xxd-style array (only for WASM)
We did an experiment to test the incbin directive on a variety of
platforms in PR #510.
This change also optimizes the size of existing images using squoosh.app.
This should make the main README a lot lighter and faster to load (it saves
several MiBs).
We're using timed condition variable in one place, but the STL version
pulls in a lot of code because it does clock calculations in
"long double" (!!!!). Since we already had an implementation
of condition_variable, we just add the timed version.
This saves several KiB of code.
Also don't use unique_lock() lock/unlock because it can throw exceptions.
The Pool wasn't used much anymore, since we're explicitly copy
the data into the command stream. Moreover, it generated a lot of code
and in fact was probably less efficient than malloc itself --
I think this was a misguided optimization in the first place.
This removes a lot of heap allocations/deallocations, and reduces
code size. Most improvements come from using CString and
StaticString instead of std::string and better using move
semantics.
Aaron pointed out that this error is easy to run into and quite cryptic
since one value is decimal and the other is hex. Users might not be
aware that one of them is a bitmask, and that this is related to how
they invoke matc or filamat.
In practice this limits materials to 10 samplers since Filament uses 5
for lights and skips 1 slot for the post-process sampler. This can
probably be optimized.
We now check for sampler overflow during material compilation rather
than waiting for run-time checks. This allows for Kokoro-based
validation of sample materials, and allows developers to catch this
issue in their asset pipeline.
We should also probably raise the upper limit (Qualcomm allows up to 16
samplers in their Vulkan implementation) but that can be a separate PR.
Fixes#507
This caused regressions with some of our samples like vk_hellopbr:
- For the new 1x1 textures, RGB isn't accepted by Vulkan and Metal.
Currently these platforms require RGBA, although we plan on adding
reshaping functionality for the future.
- Too many texture samplers in a single shader, this causes a run time
error. This could be alleviated by creating an atlas.
- vk_hellopbr assumes that all materials have a "metallic" param.
Going forward, we plan on creating a new library that avoids MeshAssimp,
so for now let's just disable gltf_viewer.
This fixes the "shader is not ASCII" error seen with GL backend,
introduced when we changed blob ownership semantics to accommodate
shader compression. It was due to missing null terminators.
We actually never bothered including the trailing null in blob length,
which was wrong but happened to work because the BlobDictionary held a
weak reference to chunk data. SInce it now holds an actual copy, the
lack of null caused our strings to contain garbage memory.
Since we use this for decoding, this adds a dependency to the core
filament renderer which in practice is only used for Vulkan. However
this is a tiny library, so it's simplest just to always include it.
The next PR will add the actual compression / decompression code to
filaflat and filamat. Here are the preliminary results.
102K => 29K aiDefaultMat.filamat
102K => 29K aiDefaultTrans.filamat
21K => 5.0K bakedColor.filamat
22K => 5.2K bakedTexture.filamat
21K => 5.0K depthVisualizer.filamat
40K => 10K groundShadow.filamat
102K => 29K sandboxCloth.filamat
125K => 36K sandboxLit.filamat
126K => 36K sandboxLitFade.filamat
126K => 36K sandboxLitTransparent.filamat
109K => 31K sandboxSubsurface.filamat
21K => 4.9K sandboxUnlit.filamat
21K => 4.9K transparentColor.filamat
Both the "before" and "after" numbers are excluding non-Vulkan targets,
and I also changed our CMakeLists to build filamat instead of inc.
Recall that Vulkan has a right-handed NDC system. Currently, our Vulkan
backend is not handling VERTEX_DOMAIN_DEVICE correctly, but we didn't
notice because the culling mode is not honored yet (a separate PR is on
the way for that).
To fix this, we considered adding a shader-based fixup only for the
device domain and keeping our Vulkanish projection matrix as-is.
However, this would cause the skybox shader to compute an incorrect
wrong eye vector due to in the inconsistent definition of clip space.
After discussion with Mathias and Ben, we decided that the most elegant
fix is for Filament to have only one canonical clip space, which for
now is the clip space that OpenGL requires.
Ben pointed out that spirv-cross has a flag for injecting shader-based
fixups. However we don't invoke spirv-cross for the Vulkan target, and
it's easy just to do this on our own.
PipelineState contains the program and raster state, more
state might be added in the future. Currently it is passed by value
and doesn't have a HwHandle, but this may change in the future.
This adds a few new functions to the JavaScript bindings. It also adds
our JavaScript docs into the CMake build system for machines that meet
the Python requirements.
This is a simple place to host WebGL demos and tutorials, we can prettify later. It will show up at:
https://google.github.io/filament/
The hugo config specifies the output holder to be ../docs which is where our GitHub Pages site is located.
Note that this commit adds the *source* to the site, it does not publish the actual site. When we're ready to publish the actual site, we'll do:
```terminal
cd site ; hugo ; cd ..
git add docs ; git commit
```
WebGL does not always honor the invariant GLSL decoration, so we cannot
allow the depth prepass on web.
This fixes the black flakes seen with the Intel HD Graphics 615 in
Pixelbook laptops.
* Clean-up EntityManager a bit
- use tsl::robin_set instead of std::set (which should have been unordered::set
anyways).
- getListeners() now returns a vector which avoids to traverse a set twice.
Turns out that copying the set wasn't as efficient as I thought.
* Improve jobsystem a bit
We recently added a job reference counting mechanism, but we were a bit
too aggressive about taking/release references.
Also make the API more complete by adding explicit retain/release,
which is needed to allow several threads to wait on the same job.
Also improve futex code by inlining it.
While this solves the builder leak, it does not solve the tiny leak
incurred every time you call `getInstance` on a component manager
without calling embind's `delete` method afterwards. Since there's no
way to auto-delete component instances, this CL fixes up our sample
code and docstrings.
Fixes#429
* Minor clean-ups
- fix a couple usage of std::function
- fix a couple usage of std::string
- remove ALIGN_LOOP, which didn't work
- fix a couple explicit/noexcept
- virtual -> override
* Fix spelling typos and other minor clang-tidy
We used to assume 32-bytes cache lines when running on ARM 32-bit mode,
however, that was wrong because 32-bit mode doesn't change the cpu's
cache line. On all modern platforms we support, the cache line
is 64 bytes.
Set Job storage to 48 bytes on all platforms.
* Fix a reuse after free in the job system
Jobs were destroyed and recycled while still in use
by wait() or run(). To fix this we introduce reference-counting of
jobs.
Jobs start with a ref-count of 1, which is decremented when a job
naturally finishes. Additionally, all user-facing methods acquire
a reference for the duration of the call.
* Fix an API inconsistency with JobSystem
JobSystem's API lets the user create jobs but not destroy them.
Jobs are destroyed automatically, without a way for the caller to
know when that happens.
We now explicitly enforce that jobs are no longer valid when
wait() returns. Multiple concurrent wait() are allowed however.
This is enforced by clearing the job pointer upon returning
from JobSystem::wait(Job* job).
* Rename linked-list put/get to push/pop
* Better fix for Job use after free
There was still a race condition where a run()'ed
job could be destroyed before wait() was called,
wait would then use a destroyed object.
The available APIs now are:
run() - runs and destroys a job
runAndWait() - run, then waits for and destroys a job
runAndRetain() - runs and keep a reference to the job
wait() - waits and destroys a job
wait() can only be used with a job obtained with runAndRetain().
* Get rid of unused code
This version of parallel_for has use-after-free issues anyways,
since we changed the semantics of run/wait/etc...
* Fix decRef() memory order
decRef() must ensure that all access to the
object have happened before destroying it.
* Fix memory order in atomic linked list's pop()
It needs acquire semantic, since we want to make
sure that no read/write are reordered before the
pop() -- which returns an object to the caller.
* Fix memory order on runningJobCount
we needed acquire semantic when about to destroy
the last job -- it's similar to decRef.
* Comment usages of std::memory_order_*
* Fix AtomicFreeList A-B-A bug
Turns out AtomicFreeList was not immune to the ABA bug. W're fixing
it here by using a 64-bits CAS, which is available on aarch64 and armv7.
Note that we need to allow clients to find out if compressed textures
are supported BEFORE the engine is created, so that they can start
downloading the correct set of texture files. To allow this, we now
expose a getSupportedFormats function that creates a throw-away canvas
in order to query extensions (creating a temporary canvas is a technique
that we also used in the old PNG decoder that we removed in 7b36ed4)
These are broken and no longer necessary now that we have web/samples.
Despite the name, these weren't real tests; they were ignored by CMake
and did not run in an automated manner. Going forward we need a better
solution for automated testing.
It turns out that it degrades performance even in cases where we
thought it would help. It seems to always trigger a "glFlush"
and has a very large CPU overhead. It looks like
glInvalidateFramebuffer() does a better job.
IF an UBO is marked as STREAM, meaning that data will
change every frame and the buffer content is invalidated
as well, then we use map/unmap buffer in asynchronous
mode to copy the data into the buffer.
This assumes the buffer is sized to be significantly
larger than the average amount of data used every
frame.
This makes our createTexture* helpers more consistent with the
createMaterial helper, and extends the wrapped Engine class with new
methods.
Before, clients did something like this:
const ao = Filament.createTextureFromPng(Filament.assets['foo.png'], engine);
...
engine.destroyTexture(ao);
Now, they can do:
const ao = engine.createTextureFromPng('foo.png');
...
engine.destroyTexture(ao);
This is more symmetric and concise. In general the JS API now supports a
class of "buffer-like" objects which exploit dynamic typing in order to
accept any of the following: BufferDescriptor, asset string, or
Uint8Array.
This test recreates a renderable every few frames and dumps the heap
pointer to the console so we can check if it increases over time.
Also simplified the personal web server script so that it uses twisted
and avoid doing a chdir, seems to be more reliable this way.
We were not normalizing one of the orthonormal basis vectors, causing
the visual aberration reported in #423.
This CL also add a "back light" to the redball demo to lighten up the
dark area in the IBL.
Fixes#423
Shameless recreation of the Android `textured-android` sample. I will
make this into a tutorial soon.
Also made some improvements to the test-builder Python script. Really,
this script exists only to make iteration easier; we need a better
solution for automated tests...
If a scene was used in several views, we would update the renderable
ubo several times per frame, which is not desirable. So we now have
such a UBO per-view. This could change in the future, depending
how we want to manage it.
We used to have a UBO for lights per scene, however it's better to
have one per view, since it depends on the camera heavily and is
limited in size.
Not doing so, could force us to upload the same UBO multiple times
per frame, for e.g. if the same scene was used in multiple views.
- move UBO declarations in UibGenerator, i.e. next
to their Uniform Interface Block definition.
This should help forgetting to update one but
not the other.
- move UniformInterfaceBlock.h and SamplerInferfaceBlock.h under
private/filament/.
- do the same things for samplers
We use the command stream to store the lights
ubo data (16K max), which avoid a copy and simplifies
the implementation. we can get rid of GpuLightBuffer.
The docgen script now looks for /// comments in the binding definitions,
and generates markdown from those. The reference page has three
sections: classes, free functions, and enums.
Before this CL, the web archive had two folders: "public" (which
contained web demos written in C++) and "filamentjs" (for the barebones
WASM).
After this CL, the web archive will instead have "dist" and "docs". The
dist folder will have the WASM and accompanying JS file, while the docs
folder has the tutorials and their accompanying demos.
If your machine has Python 3 installed, then "build -ap webgl" will
attempt to generate the JavaScript docs. If Python 3 isn't available,
this build step will be skipped. Note that our Kokoro macOS machines
already have Python 3 pre-installed.
Also removed the pipenv file to simplify the Kokoro Python environment.
Fixes#394.
This is achieved by pre-scaling the normals
transform so that the resulting normal doesn't have
any large component allowing to do the normalize()
in the fragment shader in mediump.
This must be done for skinning too.
Unlike the triangle tutorial, this is more focused on materials and 3D
rendering. While much of the verbiage is still TBD, the code snippets
already produce a functional demo after being glued together by the
tangler script.
In order to match its JavaScript counterpart, the Buffer wrapper needs
to use reference counting, and the easiest way to achieve that is
with shared_ptr.
* WIP Add helper to upload Android bitmaps to textures
* Add missing file
* Pass custom constants for bitmap formats
* Add sample app for texturing
* Update the README for samples
* Rename variable from callback to autoBitmap
This commit contains a markdown file for a "hello triangle" tutorial
as well as a Python script that does two things:
1) Extracts JavaScript code blocks from the markdown to generate the
code for the demo.
2) Converts the markdown into a nicely-rendered web page.
After we invoke the Python script for the first time, it will create
a set of files in the root docs folder, which will automatically be
published via GitHub Pages to the following URL.
https://google.github.io/filament/webgl
This gives us an official place to host the latest web demos and
tutorials.
The tutorial can be previewed
[here](https://prideout.net/prototype/webgl/tutorial_triangle.html).
More JavaScript tutorials are forthcoming.
The JS BufferDescriptor wrapper is used in two directions: JS => WASM
and WASM => JS. In both cases, it needs to be sure to delete the
underlying driver::BufferDescriptor. This is safe because the contents
of the underlying descriptor are always moved to its final destination
before the wrapper is destroyed.
The web archive now has two subfolders: public and filamentjs.
- public contains the three C++ based web demos.
- jsbindings contains the new JS bindings and Filament-only WASM module.
This adds filamentjs to libs, which builds a Filament-only WASM file.
Unlike our existing web demos, this WASM file contains no application
code.
These bindings are by no means complete, but they are sufficient for a
"hello triangle" demo that I have working locally. Sneak peak of the
Triangle JS app code:
https://gist.github.com/prideout/e9d6dd0e312146c8a287d2d109affa4d
This commit merely adds the bindings to the build. Demos and docs are
forthcoming.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.