fix normal morph target

This commit is contained in:
Nick Fisher
2021-11-23 15:51:50 +08:00
parent bb13d82114
commit 7ae6d85878
34 changed files with 1445 additions and 511 deletions

View File

@@ -1,35 +0,0 @@
package com.example.holovox_filament
import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
/** MimeticAvatarPlugin */
class MimeticAvatarPlugin: FlutterPlugin, MethodCallHandler {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private lateinit var channel : MethodChannel
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "holovox_filament")
channel.setMethodCallHandler(this)
}
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else {
result.notImplemented()
}
}
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
}

View File

@@ -1,35 +0,0 @@
package com.example.holovox_filament
import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
/** MimeticFilamentPlugin */
class MimeticFilamentPlugin: FlutterPlugin, MethodCallHandler {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private lateinit var channel : MethodChannel
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "holovox_filament")
channel.setMethodCallHandler(this)
}
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else {
result.notImplemented()
}
}
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
}

View File

@@ -1,4 +1,4 @@
#import <Flutter/Flutter.h>
@interface MimeticFilamentPlugin : NSObject<FlutterPlugin>
@interface HolovoxFilamentPlugin : NSObject<FlutterPlugin>
@end

View File

@@ -1,9 +1,9 @@
#import "MimeticFilamentPlugin.h"
#import "HolovoxFilamentPlugin.h"
#import "filament/FilamentNativeViewFactory.h"
FilamentNativeViewFactory* factory;
@implementation MimeticFilamentPlugin
@implementation HolovoxFilamentPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
factory =
[[FilamentNativeViewFactory alloc] initWithRegistrar:registrar];

View File

@@ -43,20 +43,26 @@ static void* freeResourceGlobal(void* mem, size_t size, void* misc) {
- (void)handleMethodCall:(FlutterMethodCall* _Nonnull)call result:(FlutterResult _Nonnull )result {
if([@"initialize" isEqualToString:call.method]) {
if(!call.arguments)
_viewer = new holovox::FilamentViewer(_layer, nullptr, loadResourceGlobal, freeResourceGlobal);
_viewer = new holovox::FilamentViewer(_layer, nullptr, nullptr, loadResourceGlobal, freeResourceGlobal);
else
_viewer = new holovox::FilamentViewer(_layer, [call.arguments UTF8String], loadResourceGlobal, freeResourceGlobal);
_viewer = new holovox::FilamentViewer(_layer, [call.arguments[0] UTF8String], [call.arguments[1] UTF8String], loadResourceGlobal, freeResourceGlobal);
[_controller setViewer:_viewer];
[_controller startDisplayLink];
result(@"OK");
} else if([@"loadSkybox" isEqualToString:call.method]) {
if(!_viewer)
return;
_viewer->loadSkybox([call.arguments[0] UTF8String], [call.arguments[1] UTF8String]);
result(@"OK");
} else if([@"loadGlb" isEqualToString:call.method]) {
if(!_viewer)
return; // TODO should throw exception here
_viewer->loadGlb([call.arguments UTF8String]);
result(@"OK");
} else if([@"loadGltf" isEqualToString:call.method]) {
if(!_viewer)
return;
return; // TODO should throw exception here
_viewer->loadGltf([call.arguments[0] UTF8String], [call.arguments[1] UTF8String]);
result(@"OK");
} else if([@"panStart" isEqualToString:call.method]) {

View File

@@ -13,11 +13,12 @@ A new flutter plugin project.
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*', 'src/*.*', 'src/morph/*'
s.dependency 'Filament', '~> 1.12.4'
s.source_files = 'Classes/**/*', 'src/*.*', 'src/morph/*.*', 'src/morph/UbershaderLoader.cpp'
#s.dependency 'Filament', '~> 1.12.8'
s.dependency 'Flutter'
s.platform = :ios, '12.1'
s.static_framework = true
s.vendored_libraries = "lib/*.a"
# Flutter.framework does not contain a i386 slice.
s.user_target_xcconfig = {
@@ -26,6 +27,7 @@ A new flutter plugin project.
'USER_HEADER_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/holovox_filament/ios/include" "${PODS_ROOT}/../.symlinks/plugins/holovox_filament/ios/src", "${PODS_ROOT}/../.symlinks/plugins/holovox_filament/ios/morph"',
'OTHER_CXXFLAGS' => '--std=c++17 -fmodules -fcxx-modules',
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
'LIBRARY_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/holovox_filament/ios/lib"',
#"CLANG_CXX_LIBRARY" => "libc++"
}
s.pod_target_xcconfig = {
@@ -33,8 +35,11 @@ A new flutter plugin project.
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
'OTHER_CXXFLAGS' => '--std=c++17 -fmodules -fcxx-modules',
"OTHER_LDFLAGS" => '-lfilament -lbackend -lmathio -lfilameshio -lviewer -lfilamat -lgeometry -lutils -lfilabridge -lgltfio_resources_lite -lgltfio_core -lfilament-iblprefilter -limage -lcamutils -lgltfio_resources -lmath -lfilaflat -ldracodec -libl',
'USER_HEADER_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/holovox_filament/ios/include" "${PODS_ROOT}/../.symlinks/plugins/holovox_filament/ios/src", "${PODS_ROOT}/../.symlinks/plugins/holovox_filament/ios/morph"',
'ALWAYS_SEARCH_USER_PATHS' => 'YES',
'LIBRARY_SEARCH_PATHS' => '"${PODS_ROOT}/../.symlinks/plugins/holovox_filament/ios/lib"',
}
s.swift_version = '5.0'
end

View File

@@ -16,16 +16,16 @@
//! \file
#ifndef TNT_FILAMENT_DRIVER_BUFFERDESCRIPTOR_H
#define TNT_FILAMENT_DRIVER_BUFFERDESCRIPTOR_H
#ifndef TNT_FILAMENT_BACKEND_BUFFERDESCRIPTOR_H
#define TNT_FILAMENT_BACKEND_BUFFERDESCRIPTOR_H
#include <utils/compiler.h>
#include <utils/ostream.h>
#include <stddef.h>
#include <stdint.h>
namespace filament {
namespace backend {
namespace filament::backend {
/**
* A CPU memory-buffer descriptor, typically used to transfer data from the CPU to the GPU.
@@ -91,6 +91,56 @@ public:
: buffer(const_cast<void*>(buffer)), size(size), callback(callback), user(user) {
}
// --------------------------------------------------------------------------------------------
/**
* Helper to create a BufferDescriptor that uses a KNOWN method pointer w/ object passed
* by pointer as the callback. e.g.:
* auto bd = BufferDescriptor::make(buffer, size, &Foo::method, foo);
*
* @param buffer Memory address of the CPU buffer to reference
* @param size Size of the CPU buffer in bytes
* @return a new BufferDescriptor
*/
template<typename T, void(T::*method)(void const* buffer, size_t size)>
static BufferDescriptor make(
void const* buffer, size_t size, T* data) noexcept {
return {
buffer, size,
[](void* b, size_t s, void* u) {
(*static_cast<T**>(u)->*method)(b, s);
}, data
};
}
/**
* Helper to create a BufferDescriptor that uses a functor as the callback.
*
* Caveats:
* - DO NOT CALL setCallback() when using this helper.
* - This make a heap allocation
*
* @param buffer Memory address of the CPU buffer to reference
* @param size Size of the CPU buffer in bytes
* @param functor functor of type f(void const* buffer, size_t size)
* @return a new BufferDescriptor
*/
template<typename T>
static BufferDescriptor make(
void const* buffer, size_t size, T&& functor) noexcept {
return {
buffer, size,
[](void* b, size_t s, void* u) {
T& that = *static_cast<T*>(u);
that(b, s);
delete &that;
},
new T(std::forward<T>(functor))
};
}
// --------------------------------------------------------------------------------------------
/**
* Set or replace the release callback function
* @param callback The new callback function
@@ -126,7 +176,10 @@ private:
void* user = nullptr;
};
} // namespace backend
} // namespace filament
} // namespace filament::backend
#endif // TNT_FILAMENT_DRIVER_BUFFERDESCRIPTOR_H
#if !defined(NDEBUG)
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::BufferDescriptor& b);
#endif
#endif // TNT_FILAMENT_BACKEND_BUFFERDESCRIPTOR_H

View File

@@ -16,14 +16,16 @@
//! \file
#ifndef TNT_FILAMENT_DRIVER_DRIVERENUMS_H
#define TNT_FILAMENT_DRIVER_DRIVERENUMS_H
#ifndef TNT_FILAMENT_BACKEND_DRIVERENUMS_H
#define TNT_FILAMENT_BACKEND_DRIVERENUMS_H
#include <utils/BitmaskEnum.h>
#include <utils/unwindows.h> // Because we define ERROR in the FenceStatus enum.
#include <backend/PresentCallable.h>
#include <utils/ostream.h>
#include <math/vec4.h>
#include <array> // FIXME: STL headers are not allowed in public headers
@@ -318,7 +320,7 @@ enum class PixelDataType : uint8_t {
BYTE, //!< signed byte
USHORT, //!< unsigned short (16-bit)
SHORT, //!< signed short (16-bit)
UINT, //!< unsigned int (16-bit)
UINT, //!< unsigned int (32-bit)
INT, //!< signed int (32-bit)
HALF, //!< half-float (16-bit float)
FLOAT, //!< float (32-bits float)
@@ -561,6 +563,48 @@ static constexpr bool isDepthFormat(TextureFormat format) noexcept {
}
}
static constexpr bool isUnsignedIntFormat(TextureFormat format) {
switch (format) {
case TextureFormat::R8UI:
case TextureFormat::R16UI:
case TextureFormat::R32UI:
case TextureFormat::RG8UI:
case TextureFormat::RG16UI:
case TextureFormat::RG32UI:
case TextureFormat::RGB8UI:
case TextureFormat::RGB16UI:
case TextureFormat::RGB32UI:
case TextureFormat::RGBA8UI:
case TextureFormat::RGBA16UI:
case TextureFormat::RGBA32UI:
return true;
default:
return false;
}
}
static constexpr bool isSignedIntFormat(TextureFormat format) {
switch (format) {
case TextureFormat::R8I:
case TextureFormat::R16I:
case TextureFormat::R32I:
case TextureFormat::RG8I:
case TextureFormat::RG16I:
case TextureFormat::RG32I:
case TextureFormat::RGB8I:
case TextureFormat::RGB16I:
case TextureFormat::RGB32I:
case TextureFormat::RGBA8I:
case TextureFormat::RGBA16I:
case TextureFormat::RGBA32I:
return true;
default:
return false;
}
}
//! returns whether this format a compressed format
static constexpr bool isCompressedFormat(TextureFormat format) noexcept {
return format >= TextureFormat::EAC_R11;
@@ -917,6 +961,9 @@ using FrameScheduledCallback = void(*)(PresentCallable callable, void* user);
using FrameCompletedCallback = void(*)(void* user);
enum class Workaround : uint16_t {
SPLIT_EASU
};
} // namespace backend
} // namespace filament
@@ -926,4 +973,36 @@ template<> struct utils::EnableBitMaskOperators<filament::backend::TargetBufferF
template<> struct utils::EnableBitMaskOperators<filament::backend::TextureUsage>
: public std::true_type {};
#endif // TNT_FILAMENT_DRIVER_DRIVERENUMS_H
#if !defined(NDEBUG)
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::BufferUsage usage);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::CullingMode mode);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::ElementType type);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::PixelDataFormat format);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::PixelDataType type);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::Precision precision);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::PrimitiveType type);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::TargetBufferFlags f);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::SamplerCompareFunc func);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::SamplerCompareMode mode);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::SamplerFormat format);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::SamplerMagFilter filter);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::SamplerMinFilter filter);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::SamplerParams params);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::SamplerType type);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::SamplerWrapMode wrap);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::ShaderModel model);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::TextureCubemapFace face);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::TextureFormat format);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::TextureUsage usage);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::BufferObjectBinding binding);
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::TextureSwizzle swizzle);
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::AttributeArray& type);
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::FaceOffsets& type);
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::PolygonOffset& po);
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::RasterState& rs);
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::RenderPassParams& b);
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::Viewport& v);
#endif
#endif // TNT_FILAMENT_BACKEND_DRIVERENUMS_H

View File

@@ -14,8 +14,8 @@
* limitations under the License.
*/
#ifndef TNT_FILAMENT_DRIVER_HANDLE_H
#define TNT_FILAMENT_DRIVER_HANDLE_H
#ifndef TNT_FILAMENT_BACKEND_HANDLE_H
#define TNT_FILAMENT_BACKEND_HANDLE_H
#include <utils/compiler.h>
#include <utils/Log.h>
@@ -113,4 +113,4 @@ using VertexBufferHandle = Handle<HwVertexBuffer>;
} // namespace backend
} // namespace filament
#endif // TNT_FILAMENT_DRIVER_HANDLE_H
#endif // TNT_FILAMENT_BACKEND_HANDLE_H

View File

@@ -14,8 +14,8 @@
* limitations under the License.
*/
#ifndef TNT_FILAMENT_DRIVER_PIPELINESTATE_H
#define TNT_FILAMENT_DRIVER_PIPELINESTATE_H
#ifndef TNT_FILAMENT_BACKEND_PIPELINESTATE_H
#define TNT_FILAMENT_BACKEND_PIPELINESTATE_H
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
@@ -24,8 +24,7 @@
#include <stdint.h>
namespace filament {
namespace backend {
namespace filament::backend {
//! \privatesection
@@ -39,8 +38,10 @@ struct PipelineState {
};
};
} // namespace filament::backend
} // namespace backend
} // namespace filament
#if !defined(NDEBUG)
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::PipelineState& ps);
#endif
#endif //TNT_FILAMENT_DRIVER_PIPELINESTATE_H
#endif //TNT_FILAMENT_BACKEND_PIPELINESTATE_H

View File

@@ -16,8 +16,8 @@
//! \file
#ifndef TNT_FILAMENT_DRIVER_PIXEL_BUFFERDESCRIPTOR_H
#define TNT_FILAMENT_DRIVER_PIXEL_BUFFERDESCRIPTOR_H
#ifndef TNT_FILAMENT_BACKEND_PIXELBUFFERDESCRIPTOR_H
#define TNT_FILAMENT_BACKEND_PIXELBUFFERDESCRIPTOR_H
#include <backend/BufferDescriptor.h>
#include <backend/DriverEnums.h>
@@ -105,6 +105,71 @@ public:
alignment(1) {
}
// --------------------------------------------------------------------------------------------
template<typename T, void(T::*method)(void const* buffer, size_t size)>
static PixelBufferDescriptor make(void const* buffer, size_t size,
PixelDataFormat format, PixelDataType type, uint8_t alignment,
uint32_t left, uint32_t top, uint32_t stride, T* data) noexcept {
return { buffer, size, format, type, alignment, left, top, stride,
[](void* b, size_t s, void* u) {
(*static_cast<T**>(u)->*method)(b, s); }, data };
}
template<typename T, void(T::*method)(void const* buffer, size_t size)>
static PixelBufferDescriptor make(void const* buffer, size_t size,
PixelDataFormat format, PixelDataType type, T* data) noexcept {
return { buffer, size, format, type, [](void* b, size_t s, void* u) {
(*static_cast<T**>(u)->*method)(b, s); }, data };
}
template<typename T, void(T::*method)(void const* buffer, size_t size)>
static PixelBufferDescriptor make(void const* buffer, size_t size,
backend::CompressedPixelDataType format, uint32_t imageSize, T* data) noexcept {
return { buffer, size, format, imageSize, [](void* b, size_t s, void* u) {
(*static_cast<T**>(u)->*method)(b, s); }, data
};
}
template<typename T>
static PixelBufferDescriptor make(void const* buffer, size_t size,
PixelDataFormat format, PixelDataType type, uint8_t alignment,
uint32_t left, uint32_t top, uint32_t stride, T&& functor) noexcept {
return { buffer, size, format, type, alignment, left, top, stride,
[](void* b, size_t s, void* u) {
T& that = *static_cast<T*>(u);
that(b, s);
delete &that;
}, new T(std::forward<T>(functor))
};
}
template<typename T>
static PixelBufferDescriptor make(void const* buffer, size_t size,
PixelDataFormat format, PixelDataType type, T&& functor) noexcept {
return { buffer, size, format, type,
[](void* b, size_t s, void* u) {
T& that = *static_cast<T*>(u);
that(b, s);
delete &that;
}, new T(std::forward<T>(functor))
};
}
template<typename T>
static PixelBufferDescriptor make(void const* buffer, size_t size,
backend::CompressedPixelDataType format, uint32_t imageSize, T&& functor) noexcept {
return { buffer, size, format, imageSize,
[](void* b, size_t s, void* u) {
T& that = *static_cast<T*>(u);
that(b, s);
delete &that;
}, new T(std::forward<T>(functor))
};
}
// --------------------------------------------------------------------------------------------
/**
* Computes the size in bytes needed to fit an image of given dimensions and format
*
@@ -213,4 +278,8 @@ public:
} // namespace backend
} // namespace filament
#endif // TNT_FILAMENT_DRIVER_PIXEL_BUFFERDESCRIPTOR_H
#if !defined(NDEBUG)
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::PixelBufferDescriptor& b);
#endif
#endif // TNT_FILAMENT_BACKEND_PIXELBUFFERDESCRIPTOR_H

View File

@@ -16,8 +16,8 @@
//! \file
#ifndef TNT_FILAMENT_DRIVER_PLATFORM_H
#define TNT_FILAMENT_DRIVER_PLATFORM_H
#ifndef TNT_FILAMENT_BACKEND_PLATFORM_H
#define TNT_FILAMENT_BACKEND_PLATFORM_H
#include <backend/DriverEnums.h>
@@ -100,4 +100,4 @@ public:
} // namespace backend
} // namespace filament
#endif // TNT_FILAMENT_DRIVER_PLATFORM_H
#endif // TNT_FILAMENT_BACKEND_PLATFORM_H

View File

@@ -16,8 +16,8 @@
//! \file
#ifndef TNT_FILAMENT_BACKEND_PRESENT_CALLABLE
#define TNT_FILAMENT_BACKEND_PRESENT_CALLABLE
#ifndef TNT_FILAMENT_BACKEND_PRESENTCALLABLE
#define TNT_FILAMENT_BACKEND_PRESENTCALLABLE
#include <utils/compiler.h>
@@ -101,4 +101,4 @@ using FrameFinishedCallback UTILS_DEPRECATED = void(*)(PresentCallable callable,
} // namespace backend
} // namespace filament
#endif // TNT_FILAMENT_BACKEND_PRESENT_FRAME_CALLABLE
#endif // TNT_FILAMENT_BACKEND_PRESENTCALLABLE

View File

@@ -14,8 +14,8 @@
* limitations under the License.
*/
#ifndef TNT_FILAMENT_DRIVER_TARGETBUFFERINFO_H
#define TNT_FILAMENT_DRIVER_TARGETBUFFERINFO_H
#ifndef TNT_FILAMENT_BACKEND_TARGETBUFFERINFO_H
#define TNT_FILAMENT_BACKEND_TARGETBUFFERINFO_H
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
@@ -104,4 +104,9 @@ public:
} // namespace backend
} // namespace filament
#endif //TNT_FILAMENT_DRIVER_TARGETBUFFERINFO_H
#if !defined(NDEBUG)
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::TargetBufferInfo& tbi);
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::MRT& mrt);
#endif
#endif //TNT_FILAMENT_BACKEND_TARGETBUFFERINFO_H

View File

@@ -383,7 +383,7 @@ public:
//! Returns the camera's field of view in degrees
float getFieldOfViewInDegrees(Fov direction) const noexcept;
//! Returns a Frustum object in world space
//! Returns the camera's culling Frustum in world space
class Frustum getFrustum() const noexcept;
//! Returns the entity representing this camera

View File

@@ -16,8 +16,8 @@
//! \file
#ifndef TNT_FILAMENT_COLOR_GRADING_H
#define TNT_FILAMENT_COLOR_GRADING_H
#ifndef TNT_FILAMENT_COLORGRADING_H
#define TNT_FILAMENT_COLORGRADING_H
#include <filament/FilamentAPI.h>
#include <filament/ToneMapper.h>
@@ -66,6 +66,7 @@ class FColorGrading;
*
* The various transforms held by ColorGrading are applied in the following order:
* - Exposure
* - Night adaptation
* - White balance
* - Channel mixer
* - Shadows/mid-tones/highlights
@@ -76,12 +77,14 @@ class FColorGrading;
* - Curves
* - Tone mapping
* - Luminance scaling
* - Gamut mapping
*
* Defaults
* ========
*
* Here are the default color grading options:
* - Exposure: 0.0
* - Night adaptation: 0.0
* - White balance: temperature 0, and tint 0
* - Channel mixer: red {1,0,0}, green {0,1,0}, blue {0,0,1}
* - Shadows/mid-tones/highlights: shadows {1,1,1,0}, mid-tones {1,1,1,0}, highlights {1,1,1,0},
@@ -93,6 +96,7 @@ class FColorGrading;
* - Curves: gamma {1,1,1}, midPoint {1,1,1}, and scale {1,1,1}
* - Tone mapping: ACESLegacyToneMapper
* - Luminance scaling: false
* - Gamut mapping: false
*
* @see View
*/
@@ -186,12 +190,25 @@ public:
* When luminance scaling is enabled, tone mapping is performed on the luminance of each
* pixel instead of per-channel.
*
* @param luminanceScaling Enables or disables EVILS post-tone mapping
* @param luminanceScaling Enables or disables luminance scaling post-tone mapping
*
* @return This Builder, for chaining calls
*/
Builder& luminanceScaling(bool luminanceScaling) noexcept;
/**
* Enables or disables gamut mapping to the destination color space's gamut. When gamut
* mapping is turned off, out-of-gamut colors are clipped to the destination's gamut,
* which may produce hue skews (blue skewing to purple, green to yellow, etc.). When
* gamut mapping is enabled, out-of-gamut colors are brought back in gamut by trying to
* preserve the perceived chroma and lightness of the original values.
*
* @param gamutMapping Enables or disables gamut mapping
*
* @return This Builder, for chaining calls
*/
Builder& gamutMapping(bool gamutMapping) noexcept;
/**
* Adjusts the exposure of this image. The exposure is specified in stops:
* each stop brightens (positive values) or darkens (negative values) the image by
@@ -205,6 +222,19 @@ public:
*/
Builder& exposure(float exposure) noexcept;
/**
* Controls the amount of night adaptation to replicate a more natural representation of
* low-light conditions as perceived by the human vision system. In low-light conditions,
* peak luminance sensitivity of the eye shifts toward the blue end of the color spectrum:
* darker tones appear brighter, reducing contrast, and colors are blue shifted (the darker
* the more intense the effect).
*
* @param adaptation Amount of adaptation, between 0 (no adaptation) and 1 (full adaptation).
*
* @return This Builder, for chaining calls
*/
Builder& nightAdaptation(float adaptation) noexcept;
/**
* Adjusts the while balance of the image. This can be used to remove color casts
* and correct the appearance of the white point in the scene, or to alter the
@@ -402,4 +432,4 @@ public:
} // namespace filament
#endif // TNT_FILAMENT_COLOR_GRADING_H
#endif // TNT_FILAMENT_COLORGRADING_H

View File

@@ -16,8 +16,8 @@
//! \file
#ifndef TNT_FILAMENT_DEBUG_H
#define TNT_FILAMENT_DEBUG_H
#ifndef TNT_FILAMENT_DEBUGREGISTRY_H
#define TNT_FILAMENT_DEBUGREGISTRY_H
#include <filament/FilamentAPI.h>
@@ -128,4 +128,4 @@ public:
} // namespace filament
#endif /* TNT_FILAMENT_DEBUG_H */
#endif /* TNT_FILAMENT_DEBUGREGISTRY_H */

View File

@@ -444,7 +444,7 @@ public:
/**
* Kicks the hardware thread (e.g. the OpenGL, Vulkan or Metal thread) and blocks until
* all commands to this point are executed. Note that this doesn't guarantee that the
* all commands to this point are executed. Note that does guarantee that the
* hardware is actually finished.
*
* <p>This is typically used right after destroying the <code>SwapChain</code>,
@@ -454,8 +454,25 @@ public:
*/
void flushAndWait();
/**
* Kicks the hardware thread (e.g. the OpenGL, Vulkan or Metal thread) but does not wait
* for commands to be either executed or the hardware finished.
*
* <p>This is typically used after creating a lot of objects to start draining the command
* queue which has a limited size.</p>
*/
void flush();
/**
* Drains the user callback message queue and immediately execute all pending callbacks.
*
* <p> Typically this should be called once per frame right after the application's vsync tick,
* and typically just before computing parameters (e.g. object positions) for the next frame.
* This is useful because otherwise callbacks will be executed by filament at a later time,
* which may increase latency in certain applications.</p>
*/
void pumpMessageQueues();
/**
* Returns the default Material.
*

View File

@@ -14,8 +14,8 @@
* limitations under the License.
*/
#ifndef TNT_FILAMENT_FILAMENT_API_H
#define TNT_FILAMENT_FILAMENT_API_H
#ifndef TNT_FILAMENT_FILAMENTAPI_H
#define TNT_FILAMENT_FILAMENTAPI_H
#include <utils/compiler.h>
@@ -88,4 +88,4 @@ protected:
} // namespace filament
#endif // TNT_FILAMENT_FILAMENT_API_H
#endif // TNT_FILAMENT_FILAMENTAPI_H

View File

@@ -52,8 +52,9 @@ public:
Frustum& operator=(Frustum&& rhs) noexcept = default;
/**
* Creates a frustum from a projection matrix (usually the projection * view matrix)
* @param pv a 4x4 projection matrix
* Creates a frustum from a projection matrix in GL convention
* (usually the projection * view matrix)
* @param pv a 4x4 projection matrix in GL convention
*/
explicit Frustum(const math::mat4f& pv);

View File

@@ -16,8 +16,8 @@
//! \file
#ifndef TNT_FILAMENT_INDIRECT_LIGHT_H
#define TNT_FILAMENT_INDIRECT_LIGHT_H
#ifndef TNT_FILAMENT_INDIRECTLIGHT_H
#define TNT_FILAMENT_INDIRECTLIGHT_H
#include <filament/FilamentAPI.h>
@@ -346,4 +346,4 @@ public:
} // namespace filament
#endif // TNT_FILAMENT_INDIRECT_LIGHT_H
#endif // TNT_FILAMENT_INDIRECTLIGHT_H

View File

@@ -20,6 +20,8 @@
#include <filament/FilamentAPI.h>
#include <filament/Color.h>
#include <filament/MaterialEnums.h>
#include <backend/DriverEnums.h>
#include <utils/compiler.h>
@@ -37,6 +39,7 @@ class UniformInterfaceBlock;
class UTILS_PUBLIC MaterialInstance : public FilamentAPI {
public:
using CullingMode = filament::backend::CullingMode;
using TransparencyMode = filament::TransparencyMode;
template<typename T>
using is_supported_parameter_t = typename std::enable_if<
@@ -197,6 +200,11 @@ public:
*/
void setDoubleSided(bool doubleSided) noexcept;
/**
* Specifies how transparent objects should be rendered (default is DEFAULT).
*/
void setTransparencyMode(TransparencyMode mode) noexcept;
/**
* Overrides the default triangle culling state that was set on the material.
*/

View File

@@ -0,0 +1,362 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_FILAMENT_OPTIONS_H
#define TNT_FILAMENT_OPTIONS_H
#include <filament/Color.h>
#include <stdint.h>
namespace filament {
class Texture;
enum class QualityLevel : uint8_t {
LOW,
MEDIUM,
HIGH,
ULTRA
};
enum class BlendMode : uint8_t {
OPAQUE,
TRANSLUCENT
};
/**
* Dynamic resolution can be used to either reach a desired target frame rate
* by lowering the resolution of a View, or to increase the quality when the
* rendering is faster than the target frame rate.
*
* This structure can be used to specify the minimum scale factor used when
* lowering the resolution of a View, and the maximum scale factor used when
* increasing the resolution for higher quality rendering. The scale factors
* can be controlled on each X and Y axis independently. By default, all scale
* factors are set to 1.0.
*
* enabled: enable or disables dynamic resolution on a View
*
* homogeneousScaling: by default the system scales the major axis first. Set this to true
* to force homogeneous scaling.
*
* minScale: the minimum scale in X and Y this View should use
*
* maxScale: the maximum scale in X and Y this View should use
*
* quality: upscaling quality.
* LOW: 1 bilinear tap, Medium: 4 bilinear taps, High: 9 bilinear taps (tent)
*
* \note
* Dynamic resolution is only supported on platforms where the time to render
* a frame can be measured accurately. Dynamic resolution is currently only
* supported on Android.
*
* @see Renderer::FrameRateOptions
*
*/
struct DynamicResolutionOptions {
math::float2 minScale = math::float2(0.5f); //!< minimum scale factors in x and y
math::float2 maxScale = math::float2(1.0f); //!< maximum scale factors in x and y
float sharpness = 0.9f; //!< sharpness when QualityLevel::MEDIUM or higher is used [0 (disabled), 1 (sharpest)]
bool enabled = false; //!< enable or disable dynamic resolution
bool homogeneousScaling = false; //!< set to true to force homogeneous scaling
/**
* Upscaling quality
* LOW: bilinear filtered blit. Fastest, poor quality
* MEDIUM: AMD FidelityFX FSR1 w/ mobile optimizations
* HIGH: AMD FidelityFX FSR1 w/ mobile optimizations
* ULTRA: AMD FidelityFX FSR1
* FSR1 require a well anti-aliased (MSAA or TAA), noise free scene.
*
* The default upscaling quality is set to LOW.
*/
QualityLevel quality = QualityLevel::LOW;
};
/**
* Options to control the bloom effect
*
* enabled: Enable or disable the bloom post-processing effect. Disabled by default.
*
* levels: Number of successive blurs to achieve the blur effect, the minimum is 3 and the
* maximum is 12. This value together with resolution influences the spread of the
* blur effect. This value can be silently reduced to accommodate the original
* image size.
*
* resolution: Resolution of bloom's minor axis. The minimum value is 2^levels and the
* the maximum is lower of the original resolution and 4096. This parameter is
* silently clamped to the minimum and maximum.
* It is highly recommended that this value be smaller than the target resolution
* after dynamic resolution is applied (horizontally and vertically).
*
* strength: how much of the bloom is added to the original image. Between 0 and 1.
*
* blendMode: Whether the bloom effect is purely additive (false) or mixed with the original
* image (true).
*
* anamorphism: Bloom's aspect ratio (x/y), for artistic purposes.
*
* threshold: When enabled, a threshold at 1.0 is applied on the source image, this is
* useful for artistic reasons and is usually needed when a dirt texture is used.
*
* dirt: A dirt/scratch/smudges texture (that can be RGB), which gets added to the
* bloom effect. Smudges are visible where bloom occurs. Threshold must be
* enabled for the dirt effect to work properly.
*
* dirtStrength: Strength of the dirt texture.
*/
struct BloomOptions {
enum class BlendMode : uint8_t {
ADD, //!< Bloom is modulated by the strength parameter and added to the scene
INTERPOLATE //!< Bloom is interpolated with the scene using the strength parameter
};
Texture* dirt = nullptr; //!< user provided dirt texture
float dirtStrength = 0.2f; //!< strength of the dirt texture
float strength = 0.10f; //!< bloom's strength between 0.0 and 1.0
uint32_t resolution = 360; //!< resolution of vertical axis (2^levels to 2048)
float anamorphism = 1.0f; //!< bloom x/y aspect-ratio (1/32 to 32)
uint8_t levels = 6; //!< number of blur levels (3 to 11)
BlendMode blendMode = BlendMode::ADD; //!< how the bloom effect is applied
bool threshold = true; //!< whether to threshold the source
bool enabled = false; //!< enable or disable bloom
float highlight = 1000.0f; //!< limit highlights to this value before bloom [10, +inf]
bool lensFlare = false; //!< enable screen-space lens flare
bool starburst = true; //!< enable starburst effect on lens flare
float chromaticAberration = 0.005f; //!< amount of chromatic aberration
uint8_t ghostCount = 4; //!< number of flare "ghosts"
float ghostSpacing = 0.6f; //!< spacing of the ghost in screen units [0, 1[
float ghostThreshold = 10.0f; //!< hdr threshold for the ghosts
float haloThickness = 0.1f; //!< thickness of halo in vertical screen units, 0 to disable
float haloRadius = 0.4f; //!< radius of halo in vertical screen units [0, 0.5]
float haloThreshold = 10.0f; //!< hdr threshold for the halo
};
/**
* Options to control fog in the scene
*/
struct FogOptions {
float distance = 0.0f; //!< distance in world units from the camera where the fog starts ( >= 0.0 )
float maximumOpacity = 1.0f; //!< fog's maximum opacity between 0 and 1
float height = 0.0f; //!< fog's floor in world units
float heightFalloff = 1.0f; //!< how fast fog dissipates with altitude
LinearColor color{0.5f}; //!< fog's color (linear), see fogColorFromIbl
float density = 0.1f; //!< fog's density at altitude given by 'height'
float inScatteringStart = 0.0f; //!< distance in world units from the camera where in-scattering starts
float inScatteringSize = -1.0f; //!< size of in-scattering (>0 to activate). Good values are >> 1 (e.g. ~10 - 100).
bool fogColorFromIbl = false; //!< Fog color will be modulated by the IBL color in the view direction.
bool enabled = false; //!< enable or disable fog
};
/**
* Options to control Depth of Field (DoF) effect in the scene.
*
* cocScale can be used to set the depth of field blur independently from the camera
* aperture, e.g. for artistic reasons. This can be achieved by setting:
* cocScale = cameraAperture / desiredDoFAperture
*
* @see Camera
*/
struct DepthOfFieldOptions {
enum class Filter : uint8_t {
NONE = 0,
MEDIAN = 2
};
float cocScale = 1.0f; //!< circle of confusion scale factor (amount of blur)
float maxApertureDiameter = 0.01f; //!< maximum aperture diameter in meters (zero to disable rotation)
bool enabled = false; //!< enable or disable depth of field effect
Filter filter = Filter::MEDIAN; //!< filter to use for filling gaps in the kernel
bool nativeResolution = false; //!< perform DoF processing at native resolution
/**
* Number of of rings used by the gather kernels. The number of rings affects quality
* and performance. The actual number of sample per pixel is defined
* as (ringCount * 2 - 1)^2. Here are a few commonly used values:
* 3 rings : 25 ( 5x 5 grid)
* 4 rings : 49 ( 7x 7 grid)
* 5 rings : 81 ( 9x 9 grid)
* 17 rings : 1089 (33x33 grid)
*
* With a maximum circle-of-confusion of 32, it is never necessary to use more than 17 rings.
*
* Usually all three settings below are set to the same value, however, it is often
* acceptable to use a lower ring count for the "fast tiles", which improves performance.
* Fast tiles are regions of the screen where every pixels have a similar
* circle-of-confusion radius.
*
* A value of 0 means default, which is 5 on desktop and 3 on mobile.
*
* @{
*/
uint8_t foregroundRingCount = 0; //!< number of kernel rings for foreground tiles
uint8_t backgroundRingCount = 0; //!< number of kernel rings for background tiles
uint8_t fastGatherRingCount = 0; //!< number of kernel rings for fast tiles
/** @}*/
/**
* maximum circle-of-confusion in pixels for the foreground, must be in [0, 32] range.
* A value of 0 means default, which is 32 on desktop and 24 on mobile.
*/
uint16_t maxForegroundCOC = 0;
/**
* maximum circle-of-confusion in pixels for the background, must be in [0, 32] range.
* A value of 0 means default, which is 32 on desktop and 24 on mobile.
*/
uint16_t maxBackgroundCOC = 0;
};
/**
* Options to control the vignetting effect.
*/
struct VignetteOptions {
float midPoint = 0.5f; //!< high values restrict the vignette closer to the corners, between 0 and 1
float roundness = 0.5f; //!< controls the shape of the vignette, from a rounded rectangle (0.0), to an oval (0.5), to a circle (1.0)
float feather = 0.5f; //!< softening amount of the vignette effect, between 0 and 1
LinearColorA color{0.0f, 0.0f, 0.0f, 1.0f}; //!< color of the vignette effect, alpha is currently ignored
bool enabled = false; //!< enables or disables the vignette effect
};
/**
* Structure used to set the precision of the color buffer and related quality settings.
*
* @see setRenderQuality, getRenderQuality
*/
struct RenderQuality {
/**
* Sets the quality of the HDR color buffer.
*
* A quality of HIGH or ULTRA means using an RGB16F or RGBA16F color buffer. This means
* colors in the LDR range (0..1) have a 10 bit precision. A quality of LOW or MEDIUM means
* using an R11G11B10F opaque color buffer or an RGBA16F transparent color buffer. With
* R11G11B10F colors in the LDR range have a precision of either 6 bits (red and green
* channels) or 5 bits (blue channel).
*/
QualityLevel hdrColorBuffer = QualityLevel::HIGH;
};
/**
* Options for screen space Ambient Occlusion (SSAO) and Screen Space Cone Tracing (SSCT)
* @see setAmbientOcclusionOptions()
*/
struct AmbientOcclusionOptions {
float radius = 0.3f; //!< Ambient Occlusion radius in meters, between 0 and ~10.
float power = 1.0f; //!< Controls ambient occlusion's contrast. Must be positive.
float bias = 0.0005f; //!< Self-occlusion bias in meters. Use to avoid self-occlusion. Between 0 and a few mm.
float resolution = 0.5f;//!< How each dimension of the AO buffer is scaled. Must be either 0.5 or 1.0.
float intensity = 1.0f; //!< Strength of the Ambient Occlusion effect.
float bilateralThreshold = 0.05f; //!< depth distance that constitute an edge for filtering
QualityLevel quality = QualityLevel::LOW; //!< affects # of samples used for AO.
QualityLevel lowPassFilter = QualityLevel::MEDIUM; //!< affects AO smoothness
QualityLevel upsampling = QualityLevel::LOW; //!< affects AO buffer upsampling quality
bool enabled = false; //!< enables or disables screen-space ambient occlusion
bool bentNormals = false; //!< enables bent normals computation from AO, and specular AO
float minHorizonAngleRad = 0.0f; //!< min angle in radian to consider
/**
* Screen Space Cone Tracing (SSCT) options
* Ambient shadows from dominant light
*/
struct Ssct {
float lightConeRad = 1.0f; //!< full cone angle in radian, between 0 and pi/2
float shadowDistance = 0.3f; //!< how far shadows can be cast
float contactDistanceMax = 1.0f; //!< max distance for contact
float intensity = 0.8f; //!< intensity
math::float3 lightDirection{ 0, -1, 0 }; //!< light direction
float depthBias = 0.01f; //!< depth bias in world units (mitigate self shadowing)
float depthSlopeBias = 0.01f; //!< depth slope bias (mitigate self shadowing)
uint8_t sampleCount = 4; //!< tracing sample count, between 1 and 255
uint8_t rayCount = 1; //!< # of rays to trace, between 1 and 255
bool enabled = false; //!< enables or disables SSCT
} ssct;
};
/**
* Options for Temporal Anti-aliasing (TAA)
* @see setTemporalAntiAliasingOptions()
*/
struct TemporalAntiAliasingOptions {
float filterWidth = 1.0f; //!< reconstruction filter width typically between 0 (sharper, aliased) and 1 (smoother)
float feedback = 0.04f; //!< history feedback, between 0 (maximum temporal AA) and 1 (no temporal AA).
bool enabled = false; //!< enables or disables temporal anti-aliasing
};
/**
* List of available post-processing anti-aliasing techniques.
* @see setAntiAliasing, getAntiAliasing, setSampleCount
*/
enum class AntiAliasing : uint8_t {
NONE = 0, //!< no anti aliasing performed as part of post-processing
FXAA = 1 //!< FXAA is a low-quality but very efficient type of anti-aliasing. (default).
};
/**
* List of available post-processing dithering techniques.
*/
enum class Dithering : uint8_t {
NONE = 0, //!< No dithering
TEMPORAL = 1 //!< Temporal dithering (default)
};
/**
* List of available shadow mapping techniques.
* @see setShadowType
*/
enum class ShadowType : uint8_t {
PCF, //!< percentage-closer filtered shadows (default)
VSM //!< variance shadows
};
/**
* View-level options for VSM Shadowing.
* @see setVsmShadowOptions()
* @warning This API is still experimental and subject to change.
*/
struct VsmShadowOptions {
/**
* Sets the number of anisotropic samples to use when sampling a VSM shadow map. If greater
* than 0, mipmaps will automatically be generated each frame for all lights.
*
* The number of anisotropic samples = 2 ^ vsmAnisotropy.
*/
uint8_t anisotropy = 0;
/**
* Whether to generate mipmaps for all VSM shadow maps.
*/
bool mipmapping = false;
/**
* EVSM exponent.
* The maximum value permissible is 5.54 for a shadow map in fp16, or 42.0 for a
* shadow map in fp32. Currently the shadow map bit depth is always fp16.
*/
float exponent = 5.54f;
/**
* VSM minimum variance scale, must be positive.
*/
float minVarianceScale = 0.5f;
/**
* VSM light bleeding reduction amount, between 0 and 1.
*/
float lightBleedReduction = 0.15f;
};
} // namespace filament
#endif //TNT_FILAMENT_OPTIONS_H

View File

@@ -14,8 +14,8 @@
* limitations under the License.
*/
#ifndef TNT_FILAMENT_RENDERABLECOMPONENTMANAGER_H
#define TNT_FILAMENT_RENDERABLECOMPONENTMANAGER_H
#ifndef TNT_FILAMENT_RENDERABLEMANAGER_H
#define TNT_FILAMENT_RENDERABLEMANAGER_H
#include <filament/Box.h>
#include <filament/FilamentAPI.h>
@@ -582,4 +582,4 @@ Box RenderableManager::computeAABB(VECTOR const* vertices, INDEX const* indices,
} // namespace filament
#endif // TNT_FILAMENT_RENDERABLECOMPONENTMANAGER_H
#endif // TNT_FILAMENT_RENDERABLEMANAGER_H

View File

@@ -181,7 +181,7 @@ public:
/**
* Specifies how a texture's channels map to color components
*
* Texture Swizzle is only supported is isTextureSwizzleSupported() returns true.
* Texture Swizzle is only supported if isTextureSwizzleSupported() returns true.
*
* @param r texture channel for red component
* @param g texture channel for green component

View File

@@ -14,8 +14,8 @@
* limitations under the License.
*/
#ifndef TNT_FILAMENT_TONE_MAPPER_H
#define TNT_FILAMENT_TONE_MAPPER_H
#ifndef TNT_FILAMENT_TONEMAPPER_H
#define TNT_FILAMENT_TONEMAPPER_H
#include <utils/compiler.h>
@@ -232,4 +232,4 @@ struct UTILS_PUBLIC DisplayRangeToneMapper final : public ToneMapper {
} // namespace filament
#endif // TNT_FILAMENT_TONE_MAPPER_H
#endif // TNT_FILAMENT_TONEMAPPER_H

View File

@@ -21,10 +21,12 @@
#include <filament/Color.h>
#include <filament/FilamentAPI.h>
#include <filament/Options.h>
#include <backend/DriverEnums.h>
#include <utils/compiler.h>
#include <utils/Entity.h>
#include <math/mathfwd.h>
@@ -35,7 +37,6 @@ class ColorGrading;
class MaterialInstance;
class RenderTarget;
class Scene;
class Texture;
class Viewport;
/**
@@ -61,325 +62,21 @@ class Viewport;
*/
class UTILS_PUBLIC View : public FilamentAPI {
public:
enum class QualityLevel : uint8_t {
LOW,
MEDIUM,
HIGH,
ULTRA
};
using QualityLevel = QualityLevel;
using BlendMode = BlendMode;
using AntiAliasing = AntiAliasing;
using Dithering = Dithering;
using ShadowType = ShadowType;
enum class BlendMode : uint8_t {
OPAQUE,
TRANSLUCENT
};
/**
* Dynamic resolution can be used to either reach a desired target frame rate
* by lowering the resolution of a View, or to increase the quality when the
* rendering is faster than the target frame rate.
*
* This structure can be used to specify the minimum scale factor used when
* lowering the resolution of a View, and the maximum scale factor used when
* increasing the resolution for higher quality rendering. The scale factors
* can be controlled on each X and Y axis independently. By default, all scale
* factors are set to 1.0.
*
* enabled: enable or disables dynamic resolution on a View
*
* homogeneousScaling: by default the system scales the major axis first. Set this to true
* to force homogeneous scaling.
*
* minScale: the minimum scale in X and Y this View should use
*
* maxScale: the maximum scale in X and Y this View should use
*
* quality: upscaling quality.
* LOW: 1 bilinear tap, Medium: 4 bilinear taps, High: 9 bilinear taps (tent)
*
* \note
* Dynamic resolution is only supported on platforms where the time to render
* a frame can be measured accurately. Dynamic resolution is currently only
* supported on Android.
*
* @see Renderer::FrameRateOptions
*
*/
struct DynamicResolutionOptions {
math::float2 minScale = math::float2(0.5f); //!< minimum scale factors in x and y
math::float2 maxScale = math::float2(1.0f); //!< maximum scale factors in x and y
bool enabled = false; //!< enable or disable dynamic resolution
bool homogeneousScaling = false; //!< set to true to force homogeneous scaling
QualityLevel quality = QualityLevel::LOW; //!< Upscaling quality
};
/**
* Options to control the bloom effect
*
* enabled: Enable or disable the bloom post-processing effect. Disabled by default.
*
* levels: Number of successive blurs to achieve the blur effect, the minimum is 3 and the
* maximum is 12. This value together with resolution influences the spread of the
* blur effect. This value can be silently reduced to accommodate the original
* image size.
*
* resolution: Resolution of bloom's minor axis. The minimum value is 2^levels and the
* the maximum is lower of the original resolution and 4096. This parameter is
* silently clamped to the minimum and maximum.
* It is highly recommended that this value be smaller than the target resolution
* after dynamic resolution is applied (horizontally and vertically).
*
* strength: how much of the bloom is added to the original image. Between 0 and 1.
*
* blendMode: Whether the bloom effect is purely additive (false) or mixed with the original
* image (true).
*
* anamorphism: Bloom's aspect ratio (x/y), for artistic purposes.
*
* threshold: When enabled, a threshold at 1.0 is applied on the source image, this is
* useful for artistic reasons and is usually needed when a dirt texture is used.
*
* dirt: A dirt/scratch/smudges texture (that can be RGB), which gets added to the
* bloom effect. Smudges are visible where bloom occurs. Threshold must be
* enabled for the dirt effect to work properly.
*
* dirtStrength: Strength of the dirt texture.
*/
struct BloomOptions {
enum class BlendMode : uint8_t {
ADD, //!< Bloom is modulated by the strength parameter and added to the scene
INTERPOLATE //!< Bloom is interpolated with the scene using the strength parameter
};
Texture* dirt = nullptr; //!< user provided dirt texture
float dirtStrength = 0.2f; //!< strength of the dirt texture
float strength = 0.10f; //!< bloom's strength between 0.0 and 1.0
uint32_t resolution = 360; //!< resolution of vertical axis (2^levels to 2048)
float anamorphism = 1.0f; //!< bloom x/y aspect-ratio (1/32 to 32)
uint8_t levels = 6; //!< number of blur levels (3 to 11)
BlendMode blendMode = BlendMode::ADD; //!< how the bloom effect is applied
bool threshold = true; //!< whether to threshold the source
bool enabled = false; //!< enable or disable bloom
float highlight = 1000.0f; //!< limit highlights to this value before bloom [10, +inf]
bool lensFlare = false; //!< enable screen-space lens flare
bool starburst = true; //!< enable starburst effect on lens flare
float chromaticAberration = 0.005f; //!< amount of chromatic aberration
uint8_t ghostCount = 4; //!< number of flare "ghosts"
float ghostSpacing = 0.6f; //!< spacing of the ghost in screen units [0, 1[
float ghostThreshold = 10.0f; //!< hdr threshold for the ghosts
float haloThickness = 0.1f; //!< thickness of halo in vertical screen units, 0 to disable
float haloRadius = 0.4f; //!< radius of halo in vertical screen units [0, 0.5]
float haloThreshold = 10.0f; //!< hdr threshold for the halo
};
/**
* Options to control fog in the scene
*/
struct FogOptions {
float distance = 0.0f; //!< distance in world units from the camera where the fog starts ( >= 0.0 )
float maximumOpacity = 1.0f; //!< fog's maximum opacity between 0 and 1
float height = 0.0f; //!< fog's floor in world units
float heightFalloff = 1.0f; //!< how fast fog dissipates with altitude
LinearColor color{0.5f}; //!< fog's color (linear), see fogColorFromIbl
float density = 0.1f; //!< fog's density at altitude given by 'height'
float inScatteringStart = 0.0f; //!< distance in world units from the camera where in-scattering starts
float inScatteringSize = -1.0f; //!< size of in-scattering (>0 to activate). Good values are >> 1 (e.g. ~10 - 100).
bool fogColorFromIbl = false; //!< Fog color will be modulated by the IBL color in the view direction.
bool enabled = false; //!< enable or disable fog
};
/**
* Options to control Depth of Field (DoF) effect in the scene.
*
* cocScale can be used to set the depth of field blur independently from the camera
* aperture, e.g. for artistic reasons. This can be achieved by setting:
* cocScale = cameraAperture / desiredDoFAperture
*
* @see Camera
*/
struct DepthOfFieldOptions {
enum class Filter : uint8_t {
NONE = 0,
MEDIAN = 2
};
float cocScale = 1.0f; //!< circle of confusion scale factor (amount of blur)
float maxApertureDiameter = 0.01f; //!< maximum aperture diameter in meters (zero to disable rotation)
bool enabled = false; //!< enable or disable depth of field effect
Filter filter = Filter::MEDIAN; //!< filter to use for filling gaps in the kernel
bool nativeResolution = false; //!< perform DoF processing at native resolution
/**
* Number of of rings used by the gather kernels. The number of rings affects quality
* and performance. The actual number of sample per pixel is defined
* as (ringCount * 2 - 1)^2. Here are a few commonly used values:
* 3 rings : 25 ( 5x 5 grid)
* 4 rings : 49 ( 7x 7 grid)
* 5 rings : 81 ( 9x 9 grid)
* 17 rings : 1089 (33x33 grid)
*
* With a maximum circle-of-confusion of 32, it is never necessary to use more than 17 rings.
*
* Usually all three settings below are set to the same value, however, it is often
* acceptable to use a lower ring count for the "fast tiles", which improves performance.
* Fast tiles are regions of the screen where every pixels have a similar
* circle-of-confusion radius.
*
* A value of 0 means default, which is 5 on desktop and 3 on mobile.
*
* @{
*/
uint8_t foregroundRingCount = 0; //!< number of kernel rings for foreground tiles
uint8_t backgroundRingCount = 0; //!< number of kernel rings for background tiles
uint8_t fastGatherRingCount = 0; //!< number of kernel rings for fast tiles
/** @}*/
/**
* maximum circle-of-confusion in pixels for the foreground, must be in [0, 32] range.
* A value of 0 means default, which is 32 on desktop and 24 on mobile.
*/
uint16_t maxForegroundCOC = 0;
/**
* maximum circle-of-confusion in pixels for the background, must be in [0, 32] range.
* A value of 0 means default, which is 32 on desktop and 24 on mobile.
*/
uint16_t maxBackgroundCOC = 0;
};
/**
* Options to control the vignetting effect.
*/
struct VignetteOptions {
float midPoint = 0.5f; //!< high values restrict the vignette closer to the corners, between 0 and 1
float roundness = 0.5f; //!< controls the shape of the vignette, from a rounded rectangle (0.0), to an oval (0.5), to a circle (1.0)
float feather = 0.5f; //!< softening amount of the vignette effect, between 0 and 1
LinearColorA color{0.0f, 0.0f, 0.0f, 1.0f}; //!< color of the vignette effect, alpha is currently ignored
bool enabled = false; //!< enables or disables the vignette effect
};
/**
* Structure used to set the precision of the color buffer and related quality settings.
*
* @see setRenderQuality, getRenderQuality
*/
struct RenderQuality {
/**
* Sets the quality of the HDR color buffer.
*
* A quality of HIGH or ULTRA means using an RGB16F or RGBA16F color buffer. This means
* colors in the LDR range (0..1) have a 10 bit precision. A quality of LOW or MEDIUM means
* using an R11G11B10F opaque color buffer or an RGBA16F transparent color buffer. With
* R11G11B10F colors in the LDR range have a precision of either 6 bits (red and green
* channels) or 5 bits (blue channel).
*/
QualityLevel hdrColorBuffer = QualityLevel::HIGH;
};
/**
* Options for screen space Ambient Occlusion (SSAO) and Screen Space Cone Tracing (SSCT)
* @see setAmbientOcclusionOptions()
*/
struct AmbientOcclusionOptions {
float radius = 0.3f; //!< Ambient Occlusion radius in meters, between 0 and ~10.
float power = 1.0f; //!< Controls ambient occlusion's contrast. Must be positive.
float bias = 0.0005f; //!< Self-occlusion bias in meters. Use to avoid self-occlusion. Between 0 and a few mm.
float resolution = 0.5f;//!< How each dimension of the AO buffer is scaled. Must be either 0.5 or 1.0.
float intensity = 1.0f; //!< Strength of the Ambient Occlusion effect.
float bilateralThreshold = 0.05f; //!< depth distance that constitute an edge for filtering
QualityLevel quality = QualityLevel::LOW; //!< affects # of samples used for AO.
QualityLevel lowPassFilter = QualityLevel::MEDIUM; //!< affects AO smoothness
QualityLevel upsampling = QualityLevel::LOW; //!< affects AO buffer upsampling quality
bool enabled = false; //!< enables or disables screen-space ambient occlusion
bool bentNormals = false; //!< enables bent normals computation from AO, and specular AO
float minHorizonAngleRad = 0.0f; //!< min angle in radian to consider
/**
* Screen Space Cone Tracing (SSCT) options
* Ambient shadows from dominant light
*/
struct Ssct {
float lightConeRad = 1.0f; //!< full cone angle in radian, between 0 and pi/2
float shadowDistance = 0.3f; //!< how far shadows can be cast
float contactDistanceMax = 1.0f; //!< max distance for contact
float intensity = 0.8f; //!< intensity
math::float3 lightDirection{ 0, -1, 0 }; //!< light direction
float depthBias = 0.01f; //!< depth bias in world units (mitigate self shadowing)
float depthSlopeBias = 0.01f; //!< depth slope bias (mitigate self shadowing)
uint8_t sampleCount = 4; //!< tracing sample count, between 1 and 255
uint8_t rayCount = 1; //!< # of rays to trace, between 1 and 255
bool enabled = false; //!< enables or disables SSCT
} ssct;
};
/**
* Options for Temporal Anti-aliasing (TAA)
* @see setTemporalAntiAliasingOptions()
*/
struct TemporalAntiAliasingOptions {
float filterWidth = 1.0f; //!< reconstruction filter width typically between 0 (sharper, aliased) and 1 (smoother)
float feedback = 0.04f; //!< history feedback, between 0 (maximum temporal AA) and 1 (no temporal AA).
bool enabled = false; //!< enables or disables temporal anti-aliasing
};
/**
* List of available post-processing anti-aliasing techniques.
* @see setAntiAliasing, getAntiAliasing, setSampleCount
*/
enum class AntiAliasing : uint8_t {
NONE = 0, //!< no anti aliasing performed as part of post-processing
FXAA = 1 //!< FXAA is a low-quality but very efficient type of anti-aliasing. (default).
};
/**
* List of available post-processing dithering techniques.
*/
enum class Dithering : uint8_t {
NONE = 0, //!< No dithering
TEMPORAL = 1 //!< Temporal dithering (default)
};
/**
* List of available shadow mapping techniques.
* @see setShadowType
*/
enum class ShadowType : uint8_t {
PCF, //!< percentage-closer filtered shadows (default)
VSM //!< variance shadows
};
/**
* View-level options for VSM Shadowing.
* @see setVsmShadowOptions()
* @warning This API is still experimental and subject to change.
*/
struct VsmShadowOptions {
/**
* Sets the number of anisotropic samples to use when sampling a VSM shadow map. If greater
* than 0, mipmaps will automatically be generated each frame for all lights.
*
* The number of anisotropic samples = 2 ^ vsmAnisotropy.
*/
uint8_t anisotropy = 0;
/**
* Whether to generate mipmaps for all VSM shadow maps.
*/
bool mipmapping = false;
/**
* EVSM exponent.
* The maximum value permissible is 5.54 for a shadow map in fp16, or 42.0 for a
* shadow map in fp32. Currently the shadow map bit depth is always fp16.
*/
float exponent = 5.54f;
/**
* VSM minimum variance scale, must be positive.
*/
float minVarianceScale = 0.5f;
/**
* VSM light bleeding reduction amount, between 0 and 1.
*/
float lightBleedReduction = 0.15f;
};
using DynamicResolutionOptions = DynamicResolutionOptions;
using BloomOptions = BloomOptions;
using FogOptions = FogOptions;
using DepthOfFieldOptions = DepthOfFieldOptions;
using VignetteOptions = VignetteOptions;
using RenderQuality = RenderQuality;
using AmbientOcclusionOptions = AmbientOcclusionOptions;
using TemporalAntiAliasingOptions = TemporalAntiAliasingOptions;
using VsmShadowOptions = VsmShadowOptions;
/**
* Sets the View's name. Only useful for debugging.
@@ -875,6 +572,116 @@ public:
//! debugging: returns a Camera from the point of view of *the* dominant directional light used for shadowing.
Camera const* getDirectionalLightCamera() const noexcept;
/** Result of a picking query */
struct PickingQueryResult {
utils::Entity renderable{}; //! RenderableManager Entity at the queried coordinates
float depth{}; //! Depth buffer value (1 (near plane) to 0 (infinity))
uint32_t reserved1{};
uint32_t reserved2{};
/**
* screen space coordinates in GL convention, this can be used to compute the view or
* world space position of the picking hit. For e.g.:
* clip_space_position = (fragCoords.xy / viewport.wh, fragCoords.z) * 2.0 - 1.0
* view_space_position = inverse(projection) * clip_space_position
* world_space_position = model * view_space_position
*
* The viewport, projection and model matrices can be obtained from Camera. Because
* pick() has some latency, it might be more accurate to obtain these values at the
* time the View::pick() call is made.
*/
math::float3 fragCoords; //! screen space coordinates in GL convention
};
/** User data for PickingQueryResultCallback */
struct PickingQuery {
// note: this is enough to store a std::function<> -- just saying...
void* storage[4];
};
/** callback type used for picking queries. */
using PickingQueryResultCallback = void(*)(PickingQueryResult const& result, PickingQuery* pq);
/**
* Helper for creating a picking query from Foo::method, by pointer.
* e.g.: pick<Foo, &Foo::bar>(x, y, &foo);
*
* @tparam T Class of the method to call (e.g.: Foo)
* @tparam method Method to call on T (e.g.: &Foo::bar)
* @param x Horizontal coordinate to query in the viewport with origin on the left.
* @param y Vertical coordinate to query on the viewport with origin at the bottom.
* @param data A pointer to an instance of T
*/
template<typename T, void(T::*method)(PickingQueryResult const&)>
void pick(uint32_t x, uint32_t y, T* instance) noexcept {
PickingQuery& query = pick(x, y, [](PickingQueryResult const& result, PickingQuery* pq) {
void* user = pq->storage;
(*static_cast<T**>(user)->*method)(result);
});
query.storage[0] = instance;
}
/**
* Helper for creating a picking query from Foo::method, by copy for a small object
* e.g.: pick<Foo, &Foo::bar>(x, y, foo);
*
* @tparam T Class of the method to call (e.g.: Foo)
* @tparam method Method to call on T (e.g.: &Foo::bar)
* @param x Horizontal coordinate to query in the viewport with origin on the left.
* @param y Vertical coordinate to query on the viewport with origin at the bottom.
* @param data An instance of T
*/
template<typename T, void(T::*method)(PickingQueryResult const&)>
void pick(uint32_t x, uint32_t y, T instance) noexcept {
static_assert(sizeof(instance) <= sizeof(PickingQuery::storage), "user data too large");
PickingQuery& query = pick(x, y, [](PickingQueryResult const& result, PickingQuery* pq) {
void* user = pq->storage;
T* that = static_cast<T*>(user);
(that->*method)(result);
that->~T();
});
new(query.storage) T(std::move(instance));
}
/**
* Helper for creating a picking query from a small functor
* e.g.: pick(x, y, [](PickingQueryResult const& result){});
*
* @param x Horizontal coordinate to query in the viewport with origin on the left.
* @param y Vertical coordinate to query on the viewport with origin at the bottom.
* @param functor A functor, typically a lambda function.
*/
template<typename T>
void pick(uint32_t x, uint32_t y, T functor) noexcept {
static_assert(sizeof(functor) <= sizeof(PickingQuery::storage), "functor too large");
PickingQuery& query = pick(x, y,
(PickingQueryResultCallback)[](PickingQueryResult const& result, PickingQuery* pq) {
void* user = pq->storage;
T& that = *static_cast<T*>(user);
that(result);
that.~T();
});
new(query.storage) T(std::move(functor));
}
/**
* Creates a picking query. Multiple queries can be created (e.g.: multi-touch).
* Picking queries are all executed when Renderer::render() is called on this View.
* The provided callback is guaranteed to be called at some point in the future.
*
* Typically it takes a couple frames to receive the result of a picking query.
*
* @param x Horizontal coordinate to query in the viewport with origin on the left.
* @param y Vertical coordinate to query on the viewport with origin at the bottom.
* @param callback User callback, called when the picking query result is available.
* @return A reference to a PickingQuery structure, which can be used to store up to
* 8*sizeof(void*) bytes of user data. This user data is later accessible
* in the PickingQueryResultCallback callback 3rd parameter.
*/
PickingQuery& pick(uint32_t x, uint32_t y,
PickingQueryResultCallback callback) noexcept;
/**
* List of available ambient occlusion techniques
* @deprecated use AmbientOcclusionOptions::enabled instead
@@ -905,7 +712,6 @@ public:
AmbientOcclusion getAmbientOcclusion() const noexcept;
};
} // namespace filament
#endif // TNT_FILAMENT_VIEW_H

View File

@@ -63,6 +63,9 @@ using namespace gltfio;
using namespace utils;
using namespace std::chrono;
namespace foo {
MaterialProvider* createUbershaderLoader(filament::Engine* engine);
}
namespace filament {
class IndirectLight;
@@ -70,7 +73,12 @@ namespace filament {
}
namespace gltfio {
MaterialProvider* createGPUMorphShaderLoader(const void* data, uint64_t size, Engine* engine);
MaterialProvider* createGPUMorphShaderLoader(
const void* opaqueData,
uint64_t opaqueDataSize,
const void* fadeData,
uint64_t fadeDataSize,
Engine* engine);
void decomposeMatrix(const filament::math::mat4f& mat, filament::math::float3* translation,
filament::math::quatf* rotation, filament::math::float3* scale);
}
@@ -113,12 +121,14 @@ filament::math::mat4f composeMatrix(const filament::math::float3& translation,
FilamentViewer::FilamentViewer(
void* layer,
const char* shaderPath,
const char* opaqueShaderPath,
const char* fadeShaderPath,
LoadResource loadResource,
FreeResource freeResource) : _layer(layer),
_loadResource(loadResource),
_freeResource(freeResource),
materialProviderResources(nullptr, 0) {
opaqueShaderResources(nullptr, 0),
fadeShaderResources(nullptr, 0) {
_engine = Engine::create(Engine::Backend::OPENGL);
_renderer = _engine->createRenderer();
@@ -134,13 +144,19 @@ FilamentViewer::FilamentViewer(
_swapChain = _engine->createSwapChain(_layer);
if(shaderPath) {
materialProviderResources = _loadResource(shaderPath);
_materialProvider = createGPUMorphShaderLoader(materialProviderResources.data, materialProviderResources.size, _engine);
// if(shaderPath) {
opaqueShaderResources = _loadResource(opaqueShaderPath);
fadeShaderResources = _loadResource(fadeShaderPath);
_materialProvider = createGPUMorphShaderLoader(
opaqueShaderResources.data,
opaqueShaderResources.size,
fadeShaderResources.data,
fadeShaderResources.size,
_engine);
// _freeResource((void*)rb.data, rb.size, nullptr); <- TODO this is being freed too early, need to pass to callback?
} else {
_materialProvider = createUbershaderLoader(_engine);
}
// } else {
// _materialProvider = foo::createUbershaderLoader(_engine);
// }
EntityManager& em = EntityManager::get();
_ncm = new NameComponentManager(em);
_assetLoader = AssetLoader::create({_engine, _materialProvider, _ncm, &em});
@@ -191,7 +207,8 @@ void FilamentViewer::loadResources(string relativeResourcePath) {
void FilamentViewer::releaseSourceAssets() {
std::cout << "Releasing source data" << std::endl;
_asset->releaseSourceData();
_freeResource((void*)materialProviderResources.data, materialProviderResources.size, nullptr);
_freeResource((void*)opaqueShaderResources.data, opaqueShaderResources.size, nullptr);
_freeResource((void*)fadeShaderResources.data, fadeShaderResources.size, nullptr);
}
@@ -200,6 +217,44 @@ void FilamentViewer::animateWeights(float* data, int numWeights, int length, flo
morphAnimationBuffer = std::make_unique<MorphAnimationBuffer>(data, numWeights, length / numWeights, 1000 / frameRate );
}
void FilamentViewer::loadGlb(const char* const uri) {
if(_asset) {
_resourceLoader->evictResourceData();
_scene->removeEntities(_asset->getEntities(), _asset->getEntityCount());
_assetLoader->destroyAsset(_asset);
}
_asset = nullptr;
_animator = nullptr;
ResourceBuffer rbuf = _loadResource(uri);
// Parse the glTF file and create Filament entities.
_asset = _assetLoader->createAssetFromJson((uint8_t*)rbuf.data, rbuf.size);
if (!_asset) {
std::cerr << "Unable to parse asset" << std::endl;
exit(1);
}
_resourceLoader->loadResources(_asset);
const Entity* entities = _asset->getEntities();
RenderableManager& rm = _engine->getRenderableManager();
for(int i =0; i< _asset->getEntityCount(); i++) {
Entity e = entities[i];
auto inst = rm.getInstance(e);
rm.setCulling(inst, false);
}
_animator = _asset->getAnimator();
_scene->addEntities(_asset->getEntities(), _asset->getEntityCount());
_freeResource((void*)rbuf.data, rbuf.size, nullptr);
transformToUnitCube();
}
void FilamentViewer::loadGltf(const char* const uri, const char* const relativeResourcePath) {
if(_asset) {
_resourceLoader->evictResourceData();
@@ -280,16 +335,23 @@ void FilamentViewer::playAnimation(int index) {
}
void FilamentViewer::loadSkybox(const char* const skyboxPath, const char* const iblPath) {
std::cout << "Loading skybox from " << skyboxPath << std::endl;
ResourceBuffer skyboxBuffer = _loadResource(skyboxPath);
std::cout << "Loaded skybox resource buffer of size " << skyboxBuffer.size << std::endl;
image::KtxBundle* skyboxBundle =
new image::KtxBundle(static_cast<const uint8_t*>(skyboxBuffer.data),
static_cast<uint32_t>(skyboxBuffer.size));
_skyboxTexture = image::ktx::createTexture(_engine, skyboxBundle, false);
_skyboxTexture = image::ktx::createTexture(_engine, skyboxBundle, true);
_skybox = filament::Skybox::Builder().environment(_skyboxTexture).build(*_engine);
_scene->setSkybox(_skybox);
_freeResource((void*)skyboxBuffer.data, skyboxBuffer.size, nullptr);
std::cout << "Loading IBL from " << iblPath << std::endl;
// Load IBL.
ResourceBuffer iblBuffer = _loadResource(iblPath);

View File

@@ -94,8 +94,9 @@ namespace holovox {
class FilamentViewer {
public:
FilamentViewer(void* layer, const char* shaderPath, LoadResource loadResource, FreeResource freeResource);
FilamentViewer(void* layer, const char* opaqueShaderPath, const char* fadeShaderPath, LoadResource loadResource, FreeResource freeResource);
~FilamentViewer();
void loadGlb(const char* const uri);
void loadGltf(const char* const uri, const char* relativeResourcePath);
void loadSkybox(const char* const skyboxUri, const char* const iblUri);
void updateViewportAndCameraProjection(int height, int width, float scaleFactor);
@@ -127,7 +128,8 @@ namespace holovox {
LoadResource _loadResource;
FreeResource _freeResource;
ResourceBuffer materialProviderResources;
ResourceBuffer opaqueShaderResources;
ResourceBuffer fadeShaderResources;
Scene* _scene;
View* _view;

View File

@@ -35,6 +35,16 @@ using namespace filament;
using namespace filamat;
using namespace filament::math;
using namespace utils;
#include "upcast.h"
#include <backend/Handle.h>
#include <filament/Texture.h>
#include <utils/compiler.h>
namespace gltfio {
static constexpr uint8_t kUnused = 0xff;
@@ -62,6 +72,7 @@ namespace gltfio {
targetMesh = mesh;
for(int i = 0; i < numPrimitives; i++) {
int primitiveIndex = primitiveIndices[i];
//for(int primitiveIndex = 0; primitiveIndex < targetMesh->primitives_count; primitiveIndex++) {
std::cout << "Adding primitive at index " << primitiveIndex << " to morpher " << std::endl;
addPrimitive(mesh, primitiveIndex);
}
@@ -106,7 +117,6 @@ namespace gltfio {
auto textureSize = textureWidth * 3 * sizeof(float) * prim->numTargets;
auto textureBuffer = (float *const) malloc(textureSize);
if(!textureBuffer) {
std::cout << "Error allocating texture buffer" << std::endl;
exit(-1);
@@ -117,7 +127,7 @@ namespace gltfio {
uint32_t offset = 0;
// assume the primitive morph target source buffer is laid out like:
// |target0_v0_pos * 3|target0_v0_norm * 3|target0_v1_pos * 3|target0_v1_norm * 3|...|target1_v0_pos * 3|target1_v0_norm * 3|target1_v1_pos * 3|target1_v1_norm * 3|...
// |target0_v0_pos * 3|target0_v1_pos * 3|...|target0_v0_norm * 3|target0_v1_norm * 3|...|target1_v0_pos * 3|target1_v1_pos * 3|...|target1_v0_norm * 3|target1_v1_norm * 3|...
// where:
// - target0/target1/etc is the first/second/etc morph target
// - v0/v1/etc is the first/second/etc vertex
@@ -126,7 +136,7 @@ namespace gltfio {
if(target.type == cgltf_attribute_type_position
|| (numAttributes > 1 && target.type == cgltf_attribute_type_normal)
) {
float attr = (float)textureBuffer[offset];
memcpy(textureBuffer+offset, target.bufferObject, target.bufferSize);
offset += int(target.bufferSize / sizeof(float));
}
@@ -137,7 +147,7 @@ namespace gltfio {
.height(1)
.depth(prim->numTargets)
.sampler(Texture::Sampler::SAMPLER_2D_ARRAY)
.format(Texture::InternalFormat::RGB32F)
.format(backend::TextureFormat::RGB32F)
.levels(0x01)
.build(engine);
@@ -146,8 +156,8 @@ namespace gltfio {
Texture::PixelBufferDescriptor descriptor(
textureBuffer,
textureSize,
Texture::Format::RGB,
Texture::Type::FLOAT,
backend::PixelDataFormat::RGB,
backend::PixelDataType::FLOAT,
FREE_CALLBACK,
nullptr);
prim->texture->setImage(engine, 0, 0,0, 0, textureWidth, 1, prim->numTargets, std::move(descriptor));
@@ -155,7 +165,8 @@ namespace gltfio {
for(int i = 0; i < mAsset->getMaterialInstanceCount(); i++) {
const char* name = materialInstances[i]->getName();
if(strcmp(name, prim->materialName) == 0) {
std::cout << "Found material instance for primitive under name : " << name << std::endl;
const char* m = materialInstances[i]->getMaterial()->getName();
std::cout << "Found material instance for material " << m << " and primitive under name : " << name << std::endl;
prim->materialInstance = materialInstances[i]; //std::unique_ptr<MaterialInstance>(materialInstances[i]);
break;
}
@@ -165,7 +176,7 @@ namespace gltfio {
exit(-1);
}
float dimensions[] = { (float(prim->numVertices) * float(numAttributes)), float(numAttributes), float(prim->numTargets) };
float dimensions[] = { float(prim->numVertices), float(numAttributes), float(prim->numTargets) };
prim->materialInstance->setParameter("dimensions", dimensions, 3);
// TextureSampler sampler(filament::backend::SamplerMagFilter::NEAREST, filament::TextureSampler::WrapMode::REPEAT);
@@ -214,12 +225,7 @@ namespace gltfio {
if (atype == cgltf_attribute_type_tangent) {
continue;
}
if (
atype == cgltf_attribute_type_position || (numAttributes > 1 && atype == cgltf_attribute_type_normal)
) {
// All position & normal attributes must have the same data type.
if (atype == cgltf_attribute_type_position || numAttributes > 1 && atype == cgltf_attribute_type_normal) {
assert_invariant(
!previous || previous->component_type == accessor->component_type);
assert_invariant(!previous || previous->type == accessor->type);
@@ -234,9 +240,122 @@ namespace gltfio {
animatedPrimitive->targets.push_back({data, size, targetIndex, atype});
}
}
}
}
}
animatablePrimitives.push_back(std::move(animatedPrimitive));
}
}
// assert(
// FTexture::validatePixelFormatAndType(
// backend::TextureFormat::RGB32F,
// backend::PixelDataFormat::RGB,
// backend::PixelDataType::FLOAT));
// namespace filament {
// class FEngine;
// class FStream;
// class FTexture : public Texture {
// public:
// FTexture(FEngine& engine, const Builder& builder);
// // frees driver resources, object becomes invalid
// void terminate(FEngine& engine);
// backend::Handle<backend::HwTexture> getHwHandle() const noexcept { return mHandle; }
// size_t getWidth(size_t level = 0) const noexcept;
// size_t getHeight(size_t level = 0) const noexcept;
// size_t getDepth(size_t level = 0) const noexcept;
// size_t getLevelCount() const noexcept { return mLevelCount; }
// size_t getMaxLevelCount() const noexcept { return FTexture::maxLevelCount(mWidth, mHeight); }
// Sampler getTarget() const noexcept { return mTarget; }
// InternalFormat getFormat() const noexcept { return mFormat; }
// Usage getUsage() const noexcept { return mUsage; }
// void setImage(FEngine& engine, size_t level,
// uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
// PixelBufferDescriptor&& buffer) const;
// void setImage(FEngine& engine, size_t level,
// uint32_t xoffset, uint32_t yoffset, uint32_t zoffset,
// uint32_t width, uint32_t height, uint32_t depth,
// PixelBufferDescriptor&& buffer) const;
// void setImage(FEngine& engine, size_t level,
// PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets) const;
// void generatePrefilterMipmap(FEngine& engine,
// PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets,
// PrefilterOptions const* options);
// void setExternalImage(FEngine& engine, void* image) noexcept;
// void setExternalImage(FEngine& engine, void* image, size_t plane) noexcept;
// void setExternalStream(FEngine& engine, FStream* stream) noexcept;
// void generateMipmaps(FEngine& engine) const noexcept;
// void setSampleCount(size_t sampleCount) noexcept { mSampleCount = uint8_t(sampleCount); }
// size_t getSampleCount() const noexcept { return mSampleCount; }
// bool isMultisample() const noexcept { return mSampleCount > 1; }
// bool isCompressed() const noexcept { return backend::isCompressedFormat(mFormat); }
// bool isCubemap() const noexcept { return mTarget == Sampler::SAMPLER_CUBEMAP; }
// FStream const* getStream() const noexcept { return mStream; }
// /*
// * Utilities
// */
// // synchronous call to the backend. returns whether a backend supports a particular format.
// static bool isTextureFormatSupported(FEngine& engine, InternalFormat format) noexcept;
// // synchronous call to the backend. returns whether a backend supports texture swizzling.
// static bool isTextureSwizzleSupported(FEngine& engine) noexcept;
// // storage needed on the CPU side for texture data uploads
// static size_t computeTextureDataSize(Texture::Format format, Texture::Type type,
// size_t stride, size_t height, size_t alignment) noexcept;
// // Size a of a pixel in bytes for the given format
// static size_t getFormatSize(InternalFormat format) noexcept;
// // Returns the with or height for a given mipmap level from the base value.
// static inline size_t valueForLevel(uint8_t level, size_t baseLevelValue) {
// return std::max(size_t(1), baseLevelValue >> level);
// }
// // Returns the max number of levels for a texture of given max dimensions
// static inline uint8_t maxLevelCount(uint32_t maxDimension) noexcept {
// return std::max(1, std::ilogbf(maxDimension) + 1);
// }
// // Returns the max number of levels for a texture of given dimensions
// static inline uint8_t maxLevelCount(uint32_t width, uint32_t height) noexcept {
// return std::max(1, std::ilogbf(std::max(width, height)) + 1);
// }
// static bool validatePixelFormatAndType(backend::TextureFormat internalFormat,
// backend::PixelDataFormat format, backend::PixelDataType type) noexcept;
// private:
// friend class Texture;
// FStream* mStream = nullptr;
// backend::Handle<backend::HwTexture> mHandle;
// uint32_t mWidth = 1;
// uint32_t mHeight = 1;
// uint32_t mDepth = 1;
// InternalFormat mFormat = InternalFormat::RGBA8;
// Sampler mTarget = Sampler::SAMPLER_2D;
// uint8_t mLevelCount = 1;
// uint8_t mSampleCount = 1;
// Usage mUsage = Usage::DEFAULT;
// };
// } // namespace filament

View File

@@ -67,7 +67,7 @@ namespace gltfio {
MaterialInstance* materialInstance;
};
int numAttributes = 1; // just position for now - normals not working with indexing inside shader? byte offset seems not calculated correctly
int numAttributes = 2;
void addPrimitive(cgltf_mesh const *mesh, int primitiveIndex);

View File

@@ -8,6 +8,7 @@
#include <math/mat4.h>
#include <utils/Log.h>
#include <iostream>
#include "gltfio/resources/gltfresources_lite.h"
@@ -22,7 +23,12 @@ namespace {
class GPUMorphShaderLoader : public MaterialProvider {
public:
GPUMorphShaderLoader(const void* mData, uint64_t size, filament::Engine* engine);
GPUMorphShaderLoader(
const void* opaqueMaterial,
uint64_t opaqueMaterialSize,
const void* fadeMaterial,
uint64_t fadeMaterialSize,
filament::Engine* engine);
~GPUMorphShaderLoader() {}
MaterialInstance* createMaterialInstance(MaterialKey* config, UvMap* uvmap,
@@ -42,8 +48,10 @@ namespace {
return false;
}
}
const void* mData;
const size_t mSize;
const void* opaqueData;
const size_t opaqueDataSize;
const void* fadeData;
const size_t fadeDataSize;
Material* getMaterial(const MaterialKey& config) const;
@@ -59,18 +67,41 @@ namespace {
Engine* mEngine;
};
GPUMorphShaderLoader::GPUMorphShaderLoader(const void* data, uint64_t size, Engine* engine) : mData(data), mSize(size), mEngine(engine) {
unsigned char texels[4] = {};
mDummyTexture = Texture::Builder()
.width(1).height(1)
.format(Texture::InternalFormat::RGBA8)
.build(*mEngine);
Texture::PixelBufferDescriptor pbd(texels, sizeof(texels), Texture::Format::RGBA,
Texture::Type::UBYTE);
mDummyTexture->setImage(*mEngine, 0, std::move(pbd));
#define MATINDEX(shading, alpha, sheen, transmit, volume) (volume ? 11 : (transmit ? 10 : (sheen ? 9 : (int(shading) + 3 * int(alpha)))))
GPUMorphShaderLoader::GPUMorphShaderLoader(const void* opaqueData,
uint64_t opaqueDataSize,
const void* fadeData,
uint64_t fadeDataSize,
Engine* engine) : opaqueData(opaqueData), opaqueDataSize(opaqueDataSize), fadeData(fadeData), fadeDataSize(fadeDataSize), mEngine(engine) {
// unsigned char texels[4] = {};
// mDummyTexture = Texture::Builder()
// .width(1)
// .height(1)
// .format(backend::TextureFormat::RGBA8)
// .sampler(backend::SamplerType::SAMPLER_2D_ARRAY)
// .build(*mEngine);
// Texture::PixelBufferDescriptor pbd(
// texels,
// sizeof(texels),
// backend::PixelDataFormat::RGBA,
// backend::PixelDataType::UBYTE,
// nullptr);
// mDummyTexture->setImage(*mEngine, 0,0,0,0,0,0,0,std::move(pbd));
unsigned char texels[4] = {};
mDummyTexture = Texture::Builder()
.width(1).height(1)
.format(Texture::InternalFormat::RGBA8)
.build(*mEngine);
Texture::PixelBufferDescriptor pbd(texels, sizeof(texels), Texture::Format::RGBA,
Texture::Type::UBYTE);
mDummyTexture->setImage(*mEngine, 0, std::move(pbd));
}
size_t GPUMorphShaderLoader::getMaterialsCount() const noexcept {
return sizeof(mMaterials) / sizeof(mMaterials[0]);
}
@@ -90,13 +121,33 @@ namespace {
Material* GPUMorphShaderLoader::getMaterial(const MaterialKey& config) const {
const ShadingMode shading = config.unlit ? UNLIT :
(config.useSpecularGlossiness ? SPECULAR_GLOSSINESS : LIT);
const int matindex = 0;
const int matindex = MATINDEX(shading, config.alphaMode, config.hasSheen, config.hasTransmission, config.hasVolume);
if (mMaterials[matindex] != nullptr) {
return mMaterials[matindex];
}
switch (matindex) {
case MATINDEX(LIT, AlphaMode::OPAQUE, false, false, false):
{
filamat::Package pkg = filamat::Package(opaqueData, opaqueDataSize);
mMaterials[matindex] = Material::Builder().package(pkg.getData(), pkg.getSize()).build(*mEngine);
}
break;
case MATINDEX(LIT, AlphaMode::BLEND, false, false, false):
{
filamat::Package pkg = filamat::Package(fadeData, fadeDataSize);
mMaterials[matindex] = Material::Builder().package(pkg.getData(), pkg.getSize()).build(*mEngine);
}
break;
default:
{
filamat::Package pkg = filamat::Package(fadeData, fadeDataSize);
mMaterials[matindex] = Material::Builder().package(pkg.getData(), pkg.getSize()).build(*mEngine);
}
break;
}
filamat::Package pkg = filamat::Package(mData, mSize);
return Material::Builder().package(pkg.getData(), pkg.getSize()).build(*mEngine);
return mMaterials[matindex];
}
MaterialInstance* GPUMorphShaderLoader::createMaterialInstance(MaterialKey* config, UvMap* uvmap,
@@ -145,7 +196,9 @@ namespace {
mi->setDoubleSided(config->doubleSided);
mi->setCullingMode(config->doubleSided ? CullingMode::NONE : CullingMode::BACK);
mi->setTransparencyMode(config->doubleSided ?
MaterialInstance::TransparencyMode::TWO_PASSES_TWO_SIDES :
MaterialInstance::TransparencyMode::DEFAULT);
// Initially, assume that the clear coat texture can be honored. This is changed to false when
// running into a sampler count limitation. TODO: check if these constraints can now be relaxed.
bool clearCoatNeedsTexture = true;
@@ -176,7 +229,6 @@ namespace {
getUvIndex(config->sheenRoughnessUV, config->hasSheenRoughnessTexture));
mi->setParameter("sheenColorUvMatrix", identity);
mi->setParameter("sheenRoughnessUvMatrix", identity);
}
if (config->hasVolume) {
clearCoatNeedsTexture = false;
@@ -196,6 +248,8 @@ namespace {
mi->setParameter("normalMap", mDummyTexture, sampler);
mi->setParameter("baseColorMap", mDummyTexture, sampler);
mi->setParameter("metallicRoughnessMap", mDummyTexture, sampler);
// mi->setParameter("roughnessFactor", mDummyTexture, sampler);
mi->setParameter("occlusionMap", mDummyTexture, sampler);
mi->setParameter("emissiveMap", mDummyTexture, sampler);
if (clearCoatNeedsTexture) {
@@ -227,8 +281,18 @@ namespace {
namespace gltfio {
MaterialProvider* createGPUMorphShaderLoader(const void* data, uint64_t size, filament::Engine* engine) {
return new GPUMorphShaderLoader(data, size,engine);
MaterialProvider* createGPUMorphShaderLoader(
const void* opaqueData,
uint64_t opaqueDataSize,
const void* fadeData,
uint64_t fadeDataSize,
filament::Engine* engine) {
return new GPUMorphShaderLoader(
opaqueData,
opaqueDataSize,
fadeData,
fadeDataSize,
engine);
}
} // namespace gltfio

View File

@@ -0,0 +1,308 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gltfio/MaterialProvider.h>
#include <filament/MaterialInstance.h>
#include <filament/Texture.h>
#include <filament/TextureSampler.h>
#include <math/mat4.h>
#include <utils/Log.h>
#include "gltfio/resources/gltfresources.h"
using namespace filament;
using namespace filament::math;
using namespace gltfio;
using namespace utils;
namespace {
using CullingMode = MaterialInstance::CullingMode;
class UbershaderLoader : public MaterialProvider {
public:
UbershaderLoader(filament::Engine* engine);
~UbershaderLoader() {}
MaterialInstance* createMaterialInstance(MaterialKey* config, UvMap* uvmap,
const char* label) override;
size_t getMaterialsCount() const noexcept override;
const Material* const* getMaterials() const noexcept override;
void destroyMaterials() override;
bool needsDummyData(VertexAttribute attrib) const noexcept override {
switch (attrib) {
case VertexAttribute::UV0:
case VertexAttribute::UV1:
case VertexAttribute::COLOR:
return true;
default:
return false;
}
}
Material* getMaterial(const MaterialKey& config) const;
enum ShadingMode {
UNLIT = 0,
LIT = 1,
SPECULAR_GLOSSINESS = 2,
};
mutable Material* mMaterials[12] = {};
Texture* mDummyTexture = nullptr;
Engine* mEngine;
};
#if GLTFIO_LITE
#define CREATE_MATERIAL(name) Material::Builder() \
.package(GLTFRESOURCES_LITE_ ## name ## _DATA, GLTFRESOURCES_LITE_ ## name ## _SIZE) \
.build(*mEngine);
#else
#define CREATE_MATERIAL(name) Material::Builder() \
.package(GLTFRESOURCES_ ## name ## _DATA, GLTFRESOURCES_ ## name ## _SIZE) \
.build(*mEngine);
#endif
#define MATINDEX(shading, alpha, sheen, transmit, volume) (volume ? 11 : (transmit ? 10 : (sheen ? 9 : (int(shading) + 3 * int(alpha)))))
UbershaderLoader::UbershaderLoader(Engine* engine) : mEngine(engine) {
unsigned char texels[4] = {};
mDummyTexture = Texture::Builder()
.width(1).height(1)
.format(Texture::InternalFormat::RGBA8)
.build(*mEngine);
Texture::PixelBufferDescriptor pbd(texels, sizeof(texels), Texture::Format::RGBA,
Texture::Type::UBYTE);
mDummyTexture->setImage(*mEngine, 0, std::move(pbd));
}
size_t UbershaderLoader::getMaterialsCount() const noexcept {
return sizeof(mMaterials) / sizeof(mMaterials[0]);
}
const Material* const* UbershaderLoader::getMaterials() const noexcept {
return &mMaterials[0];
}
void UbershaderLoader::destroyMaterials() {
for (auto& material : mMaterials) {
mEngine->destroy(material);
material = nullptr;
}
mEngine->destroy(mDummyTexture);
}
Material* UbershaderLoader::getMaterial(const MaterialKey& config) const {
const ShadingMode shading = config.unlit ? UNLIT :
(config.useSpecularGlossiness ? SPECULAR_GLOSSINESS : LIT);
const int matindex = MATINDEX(shading, config.alphaMode, config.hasSheen, config.hasTransmission, config.hasVolume);
if (mMaterials[matindex] != nullptr) {
return mMaterials[matindex];
}
switch (matindex) {
case MATINDEX(LIT, AlphaMode::OPAQUE, false, false, false): mMaterials[matindex] = CREATE_MATERIAL(LIT_OPAQUE); break;
case MATINDEX(LIT, AlphaMode::BLEND, false, false, false): mMaterials[matindex] = CREATE_MATERIAL(LIT_FADE); break;
case MATINDEX(LIT, AlphaMode::MASK, false, false, false): mMaterials[matindex] = CREATE_MATERIAL(LIT_MASKED); break;
case MATINDEX(UNLIT, AlphaMode::OPAQUE, false, false, false): mMaterials[matindex] = CREATE_MATERIAL(UNLIT_OPAQUE); break;
case MATINDEX(UNLIT, AlphaMode::MASK, false, false, false): mMaterials[matindex] = CREATE_MATERIAL(UNLIT_MASKED); break;
case MATINDEX(UNLIT, AlphaMode::BLEND, false, false, false): mMaterials[matindex] = CREATE_MATERIAL(UNLIT_FADE); break;
case MATINDEX(SPECULAR_GLOSSINESS, AlphaMode::OPAQUE, false, false, false): mMaterials[matindex] = CREATE_MATERIAL(SPECULARGLOSSINESS_OPAQUE); break;
case MATINDEX(SPECULAR_GLOSSINESS, AlphaMode::MASK, false, false, false): mMaterials[matindex] = CREATE_MATERIAL(SPECULARGLOSSINESS_MASKED); break;
case MATINDEX(SPECULAR_GLOSSINESS, AlphaMode::BLEND, false, false, false): mMaterials[matindex] = CREATE_MATERIAL(SPECULARGLOSSINESS_FADE); break;
case MATINDEX(0, 0, false, true, false): mMaterials[matindex] = CREATE_MATERIAL(LIT_TRANSMISSION); break;
case MATINDEX(0, 0, true, false, false): mMaterials[matindex] = CREATE_MATERIAL(LIT_SHEEN); break;
case MATINDEX(0, 0, false, false, true): mMaterials[matindex] = CREATE_MATERIAL(LIT_VOLUME); break;
}
if (mMaterials[matindex] == nullptr) {
slog.w << "Unsupported glTF material configuration; falling back to LIT_OPAQUE." << io::endl;
MaterialKey litOpaque = config;
litOpaque.alphaMode = AlphaMode::OPAQUE;
litOpaque.hasTransmission = false;
litOpaque.hasVolume = false;
litOpaque.hasSheen = false;
litOpaque.useSpecularGlossiness = false;
litOpaque.unlit = false;
return getMaterial(litOpaque);
}
return mMaterials[matindex];
}
MaterialInstance* UbershaderLoader::createMaterialInstance(MaterialKey* config, UvMap* uvmap,
const char* label) {
// Diagnostics are not supported with LOAD_UBERSHADERS, please use GENERATE_SHADERS instead.
if (config->enableDiagnostics) {
return nullptr;
}
if (config->hasVolume && config->hasSheen) {
slog.w << "Volume and sheen are not supported together in ubershader mode,"
" removing sheen (" << label << ")." << io::endl;
config->hasSheen = false;
}
if (config->hasTransmission && config->hasSheen) {
slog.w << "Transmission and sheen are not supported together in ubershader mode,"
" removing sheen (" << label << ")." << io::endl;
config->hasSheen = false;
}
const bool clearCoatConflict = config->hasVolume || config->hasTransmission || config->hasSheen;
// Due to sampler overload, disable transmission if necessary and print a friendly warning.
if (config->hasClearCoat && clearCoatConflict) {
slog.w << "Volume, transmission and sheen are not supported in ubershader mode for clearcoat"
" materials (" << label << ")." << io::endl;
config->hasVolume = false;
config->hasTransmission = false;
config->hasSheen = false;
}
constrainMaterial(config, uvmap);
auto getUvIndex = [uvmap](uint8_t srcIndex, bool hasTexture) -> int {
return hasTexture ? int(uvmap->at(srcIndex)) - 1 : -1;
};
Material* material = getMaterial(*config);
MaterialInstance* mi = material->createInstance(label);
mi->setParameter("baseColorIndex",
getUvIndex(config->baseColorUV, config->hasBaseColorTexture));
mi->setParameter("normalIndex", getUvIndex(config->normalUV, config->hasNormalTexture));
mi->setParameter("metallicRoughnessIndex",
getUvIndex(config->metallicRoughnessUV, config->hasMetallicRoughnessTexture));
mi->setParameter("aoIndex", getUvIndex(config->aoUV, config->hasOcclusionTexture));
mi->setParameter("emissiveIndex", getUvIndex(config->emissiveUV, config->hasEmissiveTexture));
mi->setDoubleSided(config->doubleSided);
mi->setCullingMode(config->doubleSided ? CullingMode::NONE : CullingMode::BACK);
mi->setTransparencyMode(config->doubleSided ?
MaterialInstance::TransparencyMode::TWO_PASSES_TWO_SIDES :
MaterialInstance::TransparencyMode::DEFAULT);
#if !GLTFIO_LITE
// Initially, assume that the clear coat texture can be honored. This is changed to false when
// running into a sampler count limitation. TODO: check if these constraints can now be relaxed.
bool clearCoatNeedsTexture = true;
mat3f identity;
mi->setParameter("baseColorUvMatrix", identity);
mi->setParameter("metallicRoughnessUvMatrix", identity);
mi->setParameter("normalUvMatrix", identity);
mi->setParameter("occlusionUvMatrix", identity);
mi->setParameter("emissiveUvMatrix", identity);
if (config->hasClearCoat) {
mi->setParameter("clearCoatIndex",
getUvIndex(config->clearCoatUV, config->hasClearCoatTexture));
mi->setParameter("clearCoatRoughnessIndex",
getUvIndex(config->clearCoatRoughnessUV, config->hasClearCoatRoughnessTexture));
mi->setParameter("clearCoatNormalIndex",
getUvIndex(config->clearCoatNormalUV, config->hasClearCoatNormalTexture));
mi->setParameter("clearCoatUvMatrix", identity);
mi->setParameter("clearCoatRoughnessUvMatrix", identity);
mi->setParameter("clearCoatNormalUvMatrix", identity);
} else {
if (config->hasSheen) {
clearCoatNeedsTexture = false;
mi->setParameter("sheenColorIndex",
getUvIndex(config->sheenColorUV, config->hasSheenColorTexture));
mi->setParameter("sheenRoughnessIndex",
getUvIndex(config->sheenRoughnessUV, config->hasSheenRoughnessTexture));
mi->setParameter("sheenColorUvMatrix", identity);
mi->setParameter("sheenRoughnessUvMatrix", identity);
}
if (config->hasVolume) {
clearCoatNeedsTexture = false;
mi->setParameter("volumeThicknessUvMatrix", identity);
mi->setParameter("volumeThicknessIndex",
getUvIndex(config->transmissionUV, config->hasVolumeThicknessTexture));
}
if (config->hasTransmission) {
clearCoatNeedsTexture = false;
mi->setParameter("transmissionUvMatrix", identity);
mi->setParameter("transmissionIndex",
getUvIndex(config->transmissionUV, config->hasTransmissionTexture));
}
}
#else
// In the GLTFIO_LITE configuration we do not support UV matrices, clear coat, sheen, specular
// glossiness, or transmission. For more details, see `gltflite.mat.in`. To configure a custom
// set of features, create your own MaterialProvider class, perhaps using UbershaderLoader as a
// starting point.
const bool clearCoatNeedsTexture = false;
#endif
TextureSampler sampler;
mi->setParameter("normalMap", mDummyTexture, sampler);
mi->setParameter("baseColorMap", mDummyTexture, sampler);
mi->setParameter("metallicRoughnessMap", mDummyTexture, sampler);
mi->setParameter("occlusionMap", mDummyTexture, sampler);
mi->setParameter("emissiveMap", mDummyTexture, sampler);
if (clearCoatNeedsTexture) {
mi->setParameter("clearCoatMap", mDummyTexture, sampler);
mi->setParameter("clearCoatRoughnessMap", mDummyTexture, sampler);
mi->setParameter("clearCoatNormalMap", mDummyTexture, sampler);
}
if (!config->hasClearCoat) {
if (config->hasTransmission) {
mi->setParameter("transmissionMap", mDummyTexture, sampler);
}
if (config->hasSheen) {
mi->setParameter("sheenColorMap", mDummyTexture, sampler);
mi->setParameter("sheenRoughnessMap", mDummyTexture, sampler);
}
}
if (mi->getMaterial()->hasParameter("ior")) {
mi->setParameter("ior", 1.5f);
}
if (mi->getMaterial()->hasParameter("reflectance")) {
mi->setParameter("reflectance", 0.5f);
}
return mi;
}
} // anonymous namespace
namespace foo {
MaterialProvider* createUbershaderLoader(filament::Engine* engine) {
return new UbershaderLoader(engine);
}
} // namespace gltfio

View File

@@ -19,7 +19,12 @@ abstract class FilamentController {
Future releaseSourceAssets();
Future playAnimation(int index);
// Weights is expected to be a contiguous sequence of floats of size W*F, where W is the number of weights and F is the number of frames
///
/// Set the weights of all morph targets in the mesh to the specified weights at successive frames (where [framerate] is the number of times per second the weights should be updated).
/// Accepts a list of doubles representing a sequence of "frames", stacked end-to-end.
/// Each frame is [numWeights] in length, where each entry is the weight to be applied to the morph target located at that index in the mesh primitive at that frame.
/// In other words, weights is a contiguous sequence of floats of size W*F, where W is the number of weights and F is the number of frames
///
Future animate(List<double> weights, int numWeights, double frameRate);
Future createMorpher(String meshName, List<int> primitives);
Future zoom(double z);
@@ -28,12 +33,10 @@ abstract class FilamentController {
class HolovoxFilamentController extends FilamentController {
late int _id;
late MethodChannel _channel;
final String materialPath;
final Function(int id)? onFilamentViewCreatedHandler;
HolovoxFilamentController(
{this.materialPath = "packages/holovox_filament/assets/compiled.mat",
this.onFilamentViewCreatedHandler});
HolovoxFilamentController({this.onFilamentViewCreatedHandler});
@override
void onFilamentViewCreated(int id) async {
@@ -51,7 +54,10 @@ class HolovoxFilamentController extends FilamentController {
@override
Future _initialize() async {
await _channel.invokeMethod("initialize", materialPath);
await _channel.invokeMethod("initialize", [
"packages/holovox_filament/assets/lit_opaque.filamat",
"packages/holovox_filament/assets/lit_fade.filamat"
]);
}
@override
@@ -59,8 +65,9 @@ class HolovoxFilamentController extends FilamentController {
await _channel.invokeMethod("loadSkybox", [skyboxPath, lightingPath]);
}
Future loadGlb(String path) {
throw Exception();
Future loadGlb(String path) async {
print("Loading GLB at $path ");
await _channel.invokeMethod("loadGlb", path);
}
Future loadGltf(String path, String relativeResourcePath) async {