More code size optimizations and bvecn fixes
MaterialInstance: generate versions of setParameter() methods that are templated on the parameter sizeof(), which allows us to coalesce implementations, e.g. vec4<float> and vec4<int> are now the same. We make the compiler generate non-inline version of all these methods, the typed version just call through, taking advantage of the tail-call optimization in clang. MaterialParser: improve code to avoid calling multiple methods that all did more or less the same thing and were inlined. PostProcessManager: use a loop to initialize the materials ToneMapping: de-dup ACES implementation And other more minor optimizations. Fix alignment issues with setting booleans in UBOs
This commit is contained in:
committed by
Mathias Agopian
parent
0815adf722
commit
d740378277
@@ -76,6 +76,7 @@ set(SRCS
|
||||
src/Stream.cpp
|
||||
src/SwapChain.cpp
|
||||
src/Texture.cpp
|
||||
src/ToneMapping.cpp
|
||||
src/UniformBuffer.cpp
|
||||
src/VertexBuffer.cpp
|
||||
src/View.cpp
|
||||
|
||||
@@ -40,13 +40,9 @@ public:
|
||||
|
||||
template<typename T>
|
||||
using is_supported_parameter_t = typename std::enable_if<
|
||||
std::is_same<bool, T>::value ||
|
||||
std::is_same<float, T>::value ||
|
||||
std::is_same<int32_t, T>::value ||
|
||||
std::is_same<uint32_t, T>::value ||
|
||||
std::is_same<math::bool2, T>::value ||
|
||||
std::is_same<math::bool3, T>::value ||
|
||||
std::is_same<math::bool4, T>::value ||
|
||||
std::is_same<math::int2, T>::value ||
|
||||
std::is_same<math::int3, T>::value ||
|
||||
std::is_same<math::int4, T>::value ||
|
||||
@@ -56,8 +52,13 @@ public:
|
||||
std::is_same<math::float2, T>::value ||
|
||||
std::is_same<math::float3, T>::value ||
|
||||
std::is_same<math::float4, T>::value ||
|
||||
std::is_same<math::mat3f, T>::value ||
|
||||
std::is_same<math::mat4f, T>::value
|
||||
std::is_same<math::mat4f, T>::value ||
|
||||
// these types are slower as they need a layout conversion
|
||||
std::is_same<bool, T>::value ||
|
||||
std::is_same<math::bool2, T>::value ||
|
||||
std::is_same<math::bool3, T>::value ||
|
||||
std::is_same<math::bool4, T>::value ||
|
||||
std::is_same<math::mat3f, T>::value
|
||||
>::type;
|
||||
|
||||
/**
|
||||
@@ -78,7 +79,7 @@ public:
|
||||
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
|
||||
*/
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
void setParameter(const char* name, T value) noexcept;
|
||||
void setParameter(const char* name, T const& value) noexcept;
|
||||
|
||||
/**
|
||||
* Set a uniform array by name
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
using namespace filament::math;
|
||||
using namespace utils;
|
||||
|
||||
@@ -37,6 +35,146 @@ namespace filament {
|
||||
|
||||
using namespace backend;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
// This is the untyped/sized version of the setParameter: we end up here for e.g. vec4<int> and
|
||||
// vec4<float>. This must not be inlined (this is the whole point).
|
||||
template<size_t Size>
|
||||
UTILS_NOINLINE
|
||||
void FMaterialInstance::setParameterUntypedImpl(const char* name, const void* value) noexcept {
|
||||
ssize_t offset = mMaterial->getUniformInterfaceBlock().getUniformOffset(name, 0);
|
||||
if (UTILS_LIKELY(offset >= 0)) {
|
||||
mUniforms.setUniformUntyped<Size>(size_t(offset), value); // handles specialization for mat3f
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
// this converts typed calls into the untyped-sized call.
|
||||
template<typename T>
|
||||
UTILS_ALWAYS_INLINE
|
||||
inline void FMaterialInstance::setParameterImpl(const char* name, T const& value) noexcept {
|
||||
static_assert(!std::is_same_v<T, math::mat3f>);
|
||||
setParameterUntypedImpl<sizeof(T)>(name, &value);
|
||||
}
|
||||
|
||||
// specialization for mat3f
|
||||
template<>
|
||||
inline void FMaterialInstance::setParameterImpl(const char* name, mat3f const& value) noexcept {
|
||||
ssize_t offset = mMaterial->getUniformInterfaceBlock().getUniformOffset(name, 0);
|
||||
if (UTILS_LIKELY(offset >= 0)) {
|
||||
mUniforms.setUniform(size_t(offset), value);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
template <typename T, typename>
|
||||
void MaterialInstance::setParameter(const char* name, T const& value) noexcept {
|
||||
upcast(this)->setParameterImpl(name, value);
|
||||
}
|
||||
|
||||
template<>
|
||||
UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, bool const& v) noexcept {
|
||||
// this kills tail-call optimization
|
||||
MaterialInstance::setParameter(name, (uint32_t)v);
|
||||
}
|
||||
|
||||
template<>
|
||||
UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, bool2 const& v) noexcept {
|
||||
// this kills tail-call optimization
|
||||
MaterialInstance::setParameter(name, uint2(v));
|
||||
}
|
||||
|
||||
template<>
|
||||
UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, bool3 const& v) noexcept {
|
||||
// this kills tail-call optimization
|
||||
MaterialInstance::setParameter(name, uint3(v));
|
||||
}
|
||||
|
||||
template<>
|
||||
UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, bool4 const& v) noexcept {
|
||||
// this kills tail-call optimization
|
||||
MaterialInstance::setParameter(name, uint4(v));
|
||||
}
|
||||
|
||||
// explicit template instantiation of our supported types
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float> (const char* name, float const& v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int32_t> (const char* name, int32_t const& v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint32_t>(const char* name, uint32_t const& v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int2> (const char* name, int2 const& v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int3> (const char* name, int3 const& v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int4> (const char* name, int4 const& v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint2> (const char* name, uint2 const& v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint3> (const char* name, uint3 const& v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint4> (const char* name, uint4 const& v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float2> (const char* name, float2 const& v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float3> (const char* name, float3 const& v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float4> (const char* name, float4 const& v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<mat3f> (const char* name, mat3f const& v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<mat4f> (const char* name, mat4f const& v) noexcept;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
template <typename T, typename>
|
||||
void MaterialInstance::setParameter(const char* name, const T* value, size_t count) noexcept {
|
||||
upcast(this)->setParameterImpl(name, value, count);
|
||||
}
|
||||
|
||||
template<>
|
||||
UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, const bool* v, size_t c) noexcept {
|
||||
auto* p = new uint32_t[c];
|
||||
std::copy_n(v, c, p);
|
||||
MaterialInstance::setParameter(name, p, c);
|
||||
delete [] p;
|
||||
}
|
||||
|
||||
template<>
|
||||
UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, const bool2* v, size_t c) noexcept {
|
||||
auto* p = new uint2[c];
|
||||
std::copy_n(v, c, p);
|
||||
MaterialInstance::setParameter(name, p, c);
|
||||
delete [] p;
|
||||
}
|
||||
|
||||
template<>
|
||||
UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, const bool3* v, size_t c) noexcept {
|
||||
auto* p = new uint3[c];
|
||||
std::copy_n(v, c, p);
|
||||
MaterialInstance::setParameter(name, p, c);
|
||||
delete [] p;
|
||||
}
|
||||
|
||||
template<>
|
||||
UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, const bool4* v, size_t c) noexcept {
|
||||
auto* p = new uint4[c];
|
||||
std::copy_n(v, c, p);
|
||||
MaterialInstance::setParameter(name, p, c);
|
||||
delete [] p;
|
||||
}
|
||||
|
||||
template<>
|
||||
UTILS_PUBLIC void MaterialInstance::setParameter<mat3f>(const char* name, const mat3f* v, size_t c) noexcept {
|
||||
// pretend each mat3 is an array of 3 float3
|
||||
MaterialInstance::setParameter(name, reinterpret_cast<math::float3 const*>(v), c * 3);
|
||||
}
|
||||
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float> (const char* name, const float *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int32_t> (const char* name, const int32_t *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint32_t>(const char* name, const uint32_t *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int2> (const char* name, const int2 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int3> (const char* name, const int3 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int4> (const char* name, const int4 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint2> (const char* name, const uint2 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint3> (const char* name, const uint3 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint4> (const char* name, const uint4 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float2> (const char* name, const float2 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float3> (const char* name, const float3 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float4> (const char* name, const float4 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<mat4f> (const char* name, const mat4f *v, size_t c) noexcept;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
FMaterialInstance::FMaterialInstance() noexcept = default;
|
||||
|
||||
FMaterialInstance::FMaterialInstance(FEngine& engine, FMaterial const* material, const char* name) :
|
||||
@@ -81,6 +219,7 @@ void FMaterialInstance::terminate(FEngine& engine) {
|
||||
driver.destroySamplerGroup(mSbHandle);
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
void FMaterialInstance::initialize(FMaterial const* material) {
|
||||
mMaterial = material;
|
||||
|
||||
@@ -98,20 +237,16 @@ void FMaterialInstance::initialize(FMaterial const* material) {
|
||||
material->getId(), material->generateMaterialInstanceId());
|
||||
|
||||
if (material->getBlendingMode() == BlendingMode::MASKED) {
|
||||
static_cast<MaterialInstance*>(this)->setParameter(
|
||||
"_maskThreshold", material->getMaskThreshold());
|
||||
setMaskThreshold(material->getMaskThreshold());
|
||||
}
|
||||
|
||||
if (material->hasDoubleSidedCapability()) {
|
||||
static_cast<MaterialInstance*>(this)->setParameter(
|
||||
"_doubleSided", material->isDoubleSided());
|
||||
setDoubleSided(material->isDoubleSided());
|
||||
}
|
||||
|
||||
if (material->hasSpecularAntiAliasing()) {
|
||||
static_cast<MaterialInstance*>(this)->setParameter(
|
||||
"_specularAntiAliasingVariance", material->getSpecularAntiAliasingVariance());
|
||||
static_cast<MaterialInstance*>(this)->setParameter(
|
||||
"_specularAntiAliasingThreshold", material->getSpecularAntiAliasingThreshold());
|
||||
setSpecularAntiAliasingVariance(material->getSpecularAntiAliasingVariance());
|
||||
setSpecularAntiAliasingThreshold(material->getSpecularAntiAliasingThreshold());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,26 +260,25 @@ void FMaterialInstance::commitSlow(DriverApi& driver) const {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename>
|
||||
inline void FMaterialInstance::setParameter(const char* name, T value) noexcept {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
template<size_t Size>
|
||||
UTILS_NOINLINE
|
||||
void FMaterialInstance::setParameterUntypedImpl(const char* name, const void* value, size_t count) noexcept {
|
||||
ssize_t offset = mMaterial->getUniformInterfaceBlock().getUniformOffset(name, 0);
|
||||
if (offset >= 0) {
|
||||
mUniforms.setUniform<T>(size_t(offset), value); // handles specialization for mat3f
|
||||
if (UTILS_LIKELY(offset >= 0)) {
|
||||
mUniforms.setUniformArrayUntyped<Size>(size_t(offset), value, count);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename >
|
||||
inline void FMaterialInstance::setParameter(const char* name, const T* value, size_t count) noexcept {
|
||||
ssize_t offset = mMaterial->getUniformInterfaceBlock().getUniformOffset(name, 0);
|
||||
if (offset >= 0) {
|
||||
mUniforms.setUniformArray<T>(size_t(offset), value, count);
|
||||
}
|
||||
template<typename T>
|
||||
UTILS_ALWAYS_INLINE
|
||||
inline void FMaterialInstance::setParameterImpl(const char* name, const T* value, size_t count) noexcept {
|
||||
static_assert(!std::is_same_v<T, math::mat3f>);
|
||||
setParameterUntypedImpl<sizeof(T)>(name, value, count);
|
||||
}
|
||||
|
||||
void FMaterialInstance::setParameter(const char* name,
|
||||
Texture const* texture, TextureSampler const& sampler) noexcept {
|
||||
setParameter(name, upcast(texture)->getHwHandle(), sampler.getSamplerParams());
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void FMaterialInstance::setParameter(const char* name,
|
||||
backend::Handle<backend::HwTexture> texture, backend::SamplerParams params) noexcept {
|
||||
@@ -152,8 +286,25 @@ void FMaterialInstance::setParameter(const char* name,
|
||||
mSamplers.setSampler(index, { texture, params });
|
||||
}
|
||||
|
||||
void FMaterialInstance::setParameterImpl(const char* name,
|
||||
Texture const* texture, TextureSampler const& sampler) noexcept {
|
||||
setParameter(name, upcast(texture)->getHwHandle(), sampler.getSamplerParams());
|
||||
}
|
||||
|
||||
void FMaterialInstance::setMaskThreshold(float threshold) noexcept {
|
||||
setParameter("_maskThreshold", math::saturate(threshold));
|
||||
}
|
||||
|
||||
void FMaterialInstance::setSpecularAntiAliasingVariance(float variance) noexcept {
|
||||
setParameter("_specularAntiAliasingVariance", math::saturate(variance));
|
||||
}
|
||||
|
||||
void FMaterialInstance::setSpecularAntiAliasingThreshold(float threshold) noexcept {
|
||||
setParameter("_specularAntiAliasingThreshold", math::saturate(threshold * threshold));
|
||||
}
|
||||
|
||||
void FMaterialInstance::setDoubleSided(bool doubleSided) noexcept {
|
||||
if (!mMaterial->hasDoubleSidedCapability()) {
|
||||
if (UTILS_UNLIKELY(!mMaterial->hasDoubleSidedCapability())) {
|
||||
slog.w << "Parent material does not have double-sided capability." << io::endl;
|
||||
return;
|
||||
}
|
||||
@@ -163,18 +314,6 @@ void FMaterialInstance::setDoubleSided(bool doubleSided) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
void FMaterialInstance::setCullingMode(CullingMode culling) noexcept {
|
||||
mCulling = culling;
|
||||
}
|
||||
|
||||
void FMaterialInstance::setColorWrite(bool enable) noexcept {
|
||||
mColorWrite = enable;
|
||||
}
|
||||
|
||||
void FMaterialInstance::setDepthWrite(bool enable) noexcept {
|
||||
mDepthWrite = enable;
|
||||
}
|
||||
|
||||
void FMaterialInstance::setDepthCulling(bool enable) noexcept {
|
||||
mDepthFunc = enable ? RasterState::DepthFunc::GE : RasterState::DepthFunc::A;
|
||||
}
|
||||
@@ -189,44 +328,6 @@ const char* FMaterialInstance::getName() const noexcept {
|
||||
return mName.c_str();
|
||||
}
|
||||
|
||||
// explicit template instantiation of our supported types
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<bool> (const char* name, bool v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<float> (const char* name, float v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<int32_t> (const char* name, int32_t v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<uint32_t>(const char* name, uint32_t v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<bool2> (const char* name, bool2 v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<bool3> (const char* name, bool3 v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<bool4> (const char* name, bool4 v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<int2> (const char* name, int2 v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<int3> (const char* name, int3 v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<int4> (const char* name, int4 v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<uint2> (const char* name, uint2 v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<uint3> (const char* name, uint3 v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<uint4> (const char* name, uint4 v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<float2> (const char* name, float2 v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<float3> (const char* name, float3 v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<float4> (const char* name, float4 v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<mat3f> (const char* name, mat3f v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<mat4f> (const char* name, mat4f v) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<bool> (const char* name, const bool *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<float> (const char* name, const float *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<int32_t> (const char* name, const int32_t *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<uint32_t>(const char* name, const uint32_t *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<bool2> (const char* name, const bool2 *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<bool3> (const char* name, const bool3 *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<bool4> (const char* name, const bool4 *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<int2> (const char* name, const int2 *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<int3> (const char* name, const int3 *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<int4> (const char* name, const int4 *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<uint2> (const char* name, const uint2 *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<uint3> (const char* name, const uint3 *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<uint4> (const char* name, const uint4 *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<float2> (const char* name, const float2 *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<float3> (const char* name, const float3 *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<float4> (const char* name, const float4 *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<mat3f> (const char* name, const mat3f *v, size_t c) noexcept;
|
||||
template UTILS_NOINLINE void FMaterialInstance::setParameter<mat4f> (const char* name, const mat4f *v, size_t c) noexcept;
|
||||
|
||||
Material const* MaterialInstance::getMaterial() const noexcept {
|
||||
return upcast(this)->getMaterial();
|
||||
}
|
||||
@@ -235,65 +336,20 @@ const char* MaterialInstance::getName() const noexcept {
|
||||
return upcast(this)->getName();
|
||||
}
|
||||
|
||||
template <typename T, typename>
|
||||
void MaterialInstance::setParameter(const char* name, T value) noexcept {
|
||||
upcast(this)->setParameter<T>(name, value);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
template <typename T, typename>
|
||||
void MaterialInstance::setParameter(const char* name, const T* value, size_t count) noexcept {
|
||||
upcast(this)->setParameter<T>(name, value, count);
|
||||
}
|
||||
|
||||
// explicit template instantiation of our supported types
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<bool> (const char* name, bool v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float> (const char* name, float v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int32_t> (const char* name, int32_t v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint32_t>(const char* name, uint32_t v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<bool2> (const char* name, bool2 v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<bool3> (const char* name, bool3 v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<bool4> (const char* name, bool4 v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int2> (const char* name, int2 v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int3> (const char* name, int3 v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int4> (const char* name, int4 v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint2> (const char* name, uint2 v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint3> (const char* name, uint3 v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint4> (const char* name, uint4 v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float2> (const char* name, float2 v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float3> (const char* name, float3 v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float4> (const char* name, float4 v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<mat3f> (const char* name, mat3f v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<mat4f> (const char* name, mat4f v) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<bool> (const char* name, const bool *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float> (const char* name, const float *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int32_t> (const char* name, const int32_t *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint32_t>(const char* name, const uint32_t *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<bool2> (const char* name, const bool2 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<bool3> (const char* name, const bool3 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<bool4> (const char* name, const bool4 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int2> (const char* name, const int2 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int3> (const char* name, const int3 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<int4> (const char* name, const int4 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint2> (const char* name, const uint2 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint3> (const char* name, const uint3 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<uint4> (const char* name, const uint4 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float2> (const char* name, const float2 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float3> (const char* name, const float3 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float4> (const char* name, const float4 *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<mat3f> (const char* name, const mat3f *v, size_t c) noexcept;
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<mat4f> (const char* name, const mat4f *v, size_t c) noexcept;
|
||||
|
||||
void MaterialInstance::setParameter(const char* name, Texture const* texture,
|
||||
TextureSampler const& sampler) noexcept {
|
||||
return upcast(this)->setParameter(name, texture, sampler);
|
||||
return upcast(this)->setParameterImpl(name, texture, sampler);
|
||||
}
|
||||
|
||||
void MaterialInstance::setParameter(const char* name, RgbType type, float3 color) noexcept {
|
||||
upcast(this)->setParameter<float3>(name, Color::toLinear(type, color));
|
||||
upcast(this)->setParameterImpl<float3>(name, Color::toLinear(type, color));
|
||||
}
|
||||
|
||||
void MaterialInstance::setParameter(const char* name, RgbaType type, float4 color) noexcept {
|
||||
upcast(this)->setParameter<float4>(name, Color::toLinear(type, color));
|
||||
upcast(this)->setParameterImpl<float4>(name, Color::toLinear(type, color));
|
||||
}
|
||||
|
||||
void MaterialInstance::setScissor(uint32_t left, uint32_t bottom, uint32_t width,
|
||||
|
||||
@@ -69,11 +69,13 @@ MaterialParser::MaterialParserDetails::MaterialParserDetails(Backend backend, co
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool MaterialParser::MaterialParserDetails::getFromSimpleChunk(filamat::ChunkType type, T* value) const noexcept {
|
||||
if (mChunkContainer.hasChunk(type)) {
|
||||
Unflattener unflattener(
|
||||
mChunkContainer.getChunkStart(type),
|
||||
mChunkContainer.getChunkEnd(type));
|
||||
UTILS_NOINLINE
|
||||
bool MaterialParser::MaterialParserDetails::getFromSimpleChunk(
|
||||
filamat::ChunkType type, T* value) const noexcept {
|
||||
ChunkContainer const& chunkContainer = mChunkContainer;
|
||||
ChunkContainer::ChunkDesc const* pChunkDesc;
|
||||
if (chunkContainer.hasChunk(type, &pChunkDesc)) {
|
||||
Unflattener unflattener(pChunkDesc->start, pChunkDesc->start + pChunkDesc->size);
|
||||
return unflattener.read(value);
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -187,32 +187,45 @@ PostProcessManager::PostProcessMaterial& PostProcessManager::getPostProcessMater
|
||||
|
||||
#define MATERIAL(n) MATERIALS_ ## n ## _DATA, MATERIALS_ ## n ## _SIZE
|
||||
|
||||
struct MaterialInfo {
|
||||
utils::StaticString name;
|
||||
uint8_t const* data;
|
||||
int size;
|
||||
};
|
||||
|
||||
static const MaterialInfo sMaterialList[] = {
|
||||
{ "sao", MATERIAL(SAO) },
|
||||
{ "mipmapDepth", MATERIAL(MIPMAPDEPTH) },
|
||||
{ "vsmMipmap", MATERIAL(VSMMIPMAP) },
|
||||
{ "bilateralBlur", MATERIAL(BILATERALBLUR) },
|
||||
{ "separableGaussianBlur", MATERIAL(SEPARABLEGAUSSIANBLUR) },
|
||||
{ "bloomDownsample", MATERIAL(BLOOMDOWNSAMPLE) },
|
||||
{ "bloomUpsample", MATERIAL(BLOOMUPSAMPLE) },
|
||||
{ "blitLow", MATERIAL(BLITLOW) },
|
||||
{ "blitMedium", MATERIAL(BLITMEDIUM) },
|
||||
{ "blitHigh", MATERIAL(BLITHIGH) },
|
||||
{ "colorGrading", MATERIAL(COLORGRADING) },
|
||||
{ "colorGradingAsSubpass", MATERIAL(COLORGRADINGASSUBPASS) },
|
||||
{ "fxaa", MATERIAL(FXAA) },
|
||||
{ "taa", MATERIAL(TAA) },
|
||||
{ "dofDownsample", MATERIAL(DOFDOWNSAMPLE) },
|
||||
{ "dofMipmap", MATERIAL(DOFMIPMAP) },
|
||||
{ "dofTiles", MATERIAL(DOFTILES) },
|
||||
{ "dofDilate", MATERIAL(DOFDILATE) },
|
||||
{ "dof", MATERIAL(DOF) },
|
||||
{ "dofMedian", MATERIAL(DOFMEDIAN) },
|
||||
{ "dofCombine", MATERIAL(DOFCOMBINE) },
|
||||
};
|
||||
|
||||
void PostProcessManager::init() noexcept {
|
||||
auto& engine = mEngine;
|
||||
DriverApi& driver = engine.getDriverApi();
|
||||
mDisableFeedbackLoops = !driver.areFeedbackLoopsSupported();
|
||||
|
||||
registerPostProcessMaterial("sao", MATERIAL(SAO));
|
||||
registerPostProcessMaterial("mipmapDepth", MATERIAL(MIPMAPDEPTH));
|
||||
registerPostProcessMaterial("vsmMipmap", MATERIAL(VSMMIPMAP));
|
||||
registerPostProcessMaterial("bilateralBlur", MATERIAL(BILATERALBLUR));
|
||||
registerPostProcessMaterial("separableGaussianBlur", MATERIAL(SEPARABLEGAUSSIANBLUR));
|
||||
registerPostProcessMaterial("bloomDownsample", MATERIAL(BLOOMDOWNSAMPLE));
|
||||
registerPostProcessMaterial("bloomUpsample", MATERIAL(BLOOMUPSAMPLE));
|
||||
registerPostProcessMaterial("blitLow", MATERIAL(BLITLOW));
|
||||
registerPostProcessMaterial("blitMedium", MATERIAL(BLITMEDIUM));
|
||||
registerPostProcessMaterial("blitHigh", MATERIAL(BLITHIGH));
|
||||
registerPostProcessMaterial("colorGrading", MATERIAL(COLORGRADING));
|
||||
registerPostProcessMaterial("colorGradingAsSubpass", MATERIAL(COLORGRADINGASSUBPASS));
|
||||
registerPostProcessMaterial("fxaa", MATERIAL(FXAA));
|
||||
registerPostProcessMaterial("taa", MATERIAL(TAA));
|
||||
registerPostProcessMaterial("dofDownsample", MATERIAL(DOFDOWNSAMPLE));
|
||||
registerPostProcessMaterial("dofMipmap", MATERIAL(DOFMIPMAP));
|
||||
registerPostProcessMaterial("dofTiles", MATERIAL(DOFTILES));
|
||||
registerPostProcessMaterial("dofDilate", MATERIAL(DOFDILATE));
|
||||
registerPostProcessMaterial("dof", MATERIAL(DOF));
|
||||
registerPostProcessMaterial("dofMedian", MATERIAL(DOFMEDIAN));
|
||||
registerPostProcessMaterial("dofCombine", MATERIAL(DOFCOMBINE));
|
||||
#pragma nounroll
|
||||
for (auto const& info : sMaterialList) {
|
||||
registerPostProcessMaterial(info.name, info.data, info.size);
|
||||
}
|
||||
|
||||
// UBO storage size.
|
||||
// The effective kernel size is (kMaxPositiveKernelSize - 1) * 4 + 1.
|
||||
|
||||
252
filament/src/ToneMapping.cpp
Normal file
252
filament/src/ToneMapping.cpp
Normal file
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ToneMapping.h"
|
||||
|
||||
namespace filament {
|
||||
namespace aces {
|
||||
|
||||
inline float rgb_2_saturation(float3 rgb) {
|
||||
// Input: ACES
|
||||
// Output: OCES
|
||||
constexpr float TINY = 1e-5f;
|
||||
float mi = min(rgb);
|
||||
float ma = max(rgb);
|
||||
return (max(ma, TINY) - max(mi, TINY)) / max(ma, 1e-2f);
|
||||
}
|
||||
|
||||
inline float rgb_2_yc(float3 rgb) {
|
||||
constexpr float ycRadiusWeight = 1.75f;
|
||||
|
||||
// Converts RGB to a luminance proxy, here called YC
|
||||
// YC is ~ Y + K * Chroma
|
||||
// Constant YC is a cone-shaped surface in RGB space, with the tip on the
|
||||
// neutral axis, towards white.
|
||||
// YC is normalized: RGB 1 1 1 maps to YC = 1
|
||||
//
|
||||
// ycRadiusWeight defaults to 1.75, although can be overridden in function
|
||||
// call to rgb_2_yc
|
||||
// ycRadiusWeight = 1 -> YC for pure cyan, magenta, yellow == YC for neutral
|
||||
// of same value
|
||||
// ycRadiusWeight = 2 -> YC for pure red, green, blue == YC for neutral of
|
||||
// same value.
|
||||
|
||||
float r = rgb.r;
|
||||
float g = rgb.g;
|
||||
float b = rgb.b;
|
||||
|
||||
float chroma = std::sqrt(b * (b - g) + g * (g - r) + r * (r - b));
|
||||
|
||||
return (b + g + r + ycRadiusWeight * chroma) / 3.0f;
|
||||
}
|
||||
|
||||
inline float sigmoid_shaper(float x) {
|
||||
// Sigmoid function in the range 0 to 1 spanning -2 to +2.
|
||||
float t = max(1.0f - std::abs(x / 2.0f), 0.0f);
|
||||
float y = 1.0f + sign(x) * (1.0f - t * t);
|
||||
return y / 2.0f;
|
||||
}
|
||||
|
||||
inline float glow_fwd(float ycIn, float glowGainIn, float glowMid) {
|
||||
float glowGainOut;
|
||||
|
||||
if (ycIn <= 2.0f / 3.0f * glowMid) {
|
||||
glowGainOut = glowGainIn;
|
||||
} else if ( ycIn >= 2.0f * glowMid) {
|
||||
glowGainOut = 0.0f;
|
||||
} else {
|
||||
glowGainOut = glowGainIn * (glowMid / ycIn - 1.0f / 2.0f);
|
||||
}
|
||||
|
||||
return glowGainOut;
|
||||
}
|
||||
|
||||
inline float rgb_2_hue(float3 rgb) {
|
||||
// Returns a geometric hue angle in degrees (0-360) based on RGB values.
|
||||
// For neutral colors, hue is undefined and the function will return a quiet NaN value.
|
||||
float hue = 0.0f;
|
||||
// RGB triplets where RGB are equal have an undefined hue
|
||||
if (!(rgb.x == rgb.y && rgb.y == rgb.z)) {
|
||||
hue = f::RAD_TO_DEG * std::atan2(
|
||||
std::sqrt(3.0f) * (rgb.y - rgb.z),
|
||||
2.0f * rgb.x - rgb.y - rgb.z);
|
||||
}
|
||||
return (hue < 0.0f) ? hue + 360.0f : hue;
|
||||
}
|
||||
|
||||
inline float center_hue(float hue, float centerH) {
|
||||
float hueCentered = hue - centerH;
|
||||
if (hueCentered < -180.0f) {
|
||||
hueCentered = hueCentered + 360.0f;
|
||||
} else if (hueCentered > 180.0f) {
|
||||
hueCentered = hueCentered - 360.0f;
|
||||
}
|
||||
return hueCentered;
|
||||
}
|
||||
|
||||
inline float3 darkSurround_to_dimSurround(float3 linearCV) {
|
||||
constexpr float DIM_SURROUND_GAMMA = 0.9811f;
|
||||
|
||||
float3 XYZ = AP1_to_XYZ * linearCV;
|
||||
float3 xyY = XYZ_to_xyY(XYZ);
|
||||
|
||||
xyY.z = clamp(xyY.z, 0.0f, (float)std::numeric_limits<math::half>::max());
|
||||
xyY.z = std::pow(xyY.z, DIM_SURROUND_GAMMA);
|
||||
|
||||
XYZ = xyY_to_XYZ(xyY);
|
||||
return XYZ_to_AP1 * XYZ;
|
||||
}
|
||||
|
||||
float3 ACES(float3 color, float brightness) noexcept {
|
||||
// Some bits were removed to adapt to our desired output
|
||||
// Input: ACEScg (AP1)
|
||||
// Output: ACEScg (AP1)
|
||||
|
||||
// "Glow" module constants
|
||||
constexpr float RRT_GLOW_GAIN = 0.05f;
|
||||
constexpr float RRT_GLOW_MID = 0.08f;
|
||||
|
||||
// Red modifier constants
|
||||
constexpr float RRT_RED_SCALE = 0.82f;
|
||||
constexpr float RRT_RED_PIVOT = 0.03f;
|
||||
constexpr float RRT_RED_HUE = 0.0f;
|
||||
constexpr float RRT_RED_WIDTH = 135.0f;
|
||||
|
||||
// Desaturation constants
|
||||
constexpr float RRT_SAT_FACTOR = 0.96f;
|
||||
constexpr float ODT_SAT_FACTOR = 0.93f;
|
||||
|
||||
float3 ap0 = AP1_to_AP0 * color;
|
||||
|
||||
// Glow module
|
||||
float saturation = rgb_2_saturation(ap0);
|
||||
float ycIn = rgb_2_yc(ap0);
|
||||
float s = sigmoid_shaper((saturation - 0.4f) / 0.2f);
|
||||
float addedGlow = 1.0f + glow_fwd(ycIn, RRT_GLOW_GAIN * s, RRT_GLOW_MID);
|
||||
ap0 *= addedGlow;
|
||||
|
||||
// Red modifier
|
||||
float hue = rgb_2_hue(ap0);
|
||||
float centeredHue = center_hue(hue, RRT_RED_HUE);
|
||||
float hueWeight = smoothstep(0.0f, 1.0f, 1.0f - std::abs(2.0f * centeredHue / RRT_RED_WIDTH));
|
||||
hueWeight *= hueWeight;
|
||||
|
||||
ap0.r += hueWeight * saturation * (RRT_RED_PIVOT - ap0.r) * (1.0f - RRT_RED_SCALE);
|
||||
|
||||
// ACES to RGB rendering space
|
||||
float3 ap1 = clamp(AP0_to_AP1 * ap0, 0.0f, (float) std::numeric_limits<math::half>::max());
|
||||
|
||||
// Global desaturation
|
||||
ap1 = mix(float3(dot(ap1, LUMA_AP1)), ap1, RRT_SAT_FACTOR);
|
||||
|
||||
// NOTE: This is specific to Filament and added only to match ACES to our legacy tone mapper
|
||||
// which was a fit of ACES in Rec.709 but with a brightness boost.
|
||||
ap1 *= brightness;
|
||||
|
||||
// Fitting of RRT + ODT (RGB monitor 100 nits dim) from:
|
||||
// https://github.com/colour-science/colour-unity/blob/master/Assets/Colour/Notebooks/CIECAM02_Unity.ipynb
|
||||
constexpr float a = 2.785085f;
|
||||
constexpr float b = 0.107772f;
|
||||
constexpr float c = 2.936045f;
|
||||
constexpr float d = 0.887122f;
|
||||
constexpr float e = 0.806889f;
|
||||
float3 rgbPost = (ap1 * (a * ap1 + b)) / (ap1 * (c * ap1 + d) + e);
|
||||
|
||||
// Apply gamma adjustment to compensate for dim surround
|
||||
float3 linearCV = darkSurround_to_dimSurround(rgbPost);
|
||||
|
||||
// Apply desaturation to compensate for luminance difference
|
||||
linearCV = mix(float3(dot(linearCV, LUMA_AP1)), linearCV, ODT_SAT_FACTOR);
|
||||
|
||||
return linearCV;
|
||||
}
|
||||
|
||||
} // namespace aces
|
||||
|
||||
|
||||
namespace tonemap {
|
||||
|
||||
float3 ACES(float3 x) noexcept {
|
||||
return aces::ACES(x, 1.0f);
|
||||
}
|
||||
|
||||
float3 ACES_Legacy(float3 x) noexcept {
|
||||
return aces::ACES(x, 1.0f / 0.6f);
|
||||
}
|
||||
|
||||
float3 Uchimura(float3 x) noexcept {
|
||||
// Uchimura 2017, "HDR theory and practice"
|
||||
// Math: https://www.desmos.com/calculator/gslcdxvipg
|
||||
// Source: https://www.slideshare.net/nikuque/hdr-theory-and-practicce-jp
|
||||
|
||||
constexpr float P = 1.0; // max display brightness
|
||||
constexpr float a = 1.0; // contrast
|
||||
constexpr float m = 0.22; // linear section start
|
||||
constexpr float l = 0.4; // linear section length
|
||||
constexpr float c = 1.33; // black
|
||||
constexpr float b = 0.0; // pedestal
|
||||
|
||||
constexpr float l0 = ((P - m) * l) / a;
|
||||
constexpr float S0 = m + l0;
|
||||
constexpr float S1 = m + a * l0;
|
||||
constexpr float C2 = (a * P) / (P - S1);
|
||||
constexpr float CP = -C2 / P;
|
||||
|
||||
float3 w0 = 1.0f - smoothstep(0.0f, m, x);
|
||||
float3 w2 = step(m + l0, x);
|
||||
float3 w1 = 1.0f - w0 - w2;
|
||||
|
||||
float3 T = m * pow(x / m, c) + b;
|
||||
float3 S = P - (P - S1) * exp(CP * (x - S0));
|
||||
float3 L = m + a * (x - m);
|
||||
|
||||
return T * w0 + L * w1 + S * w2;
|
||||
}
|
||||
|
||||
float3 DisplayRange(float3 x) noexcept {
|
||||
// 16 debug colors + 1 duplicated at the end for easy indexing
|
||||
|
||||
constexpr float3 debugColors[17] = {
|
||||
{0.0, 0.0, 0.0}, // black
|
||||
{0.0, 0.0, 0.1647}, // darkest blue
|
||||
{0.0, 0.0, 0.3647}, // darker blue
|
||||
{0.0, 0.0, 0.6647}, // dark blue
|
||||
{0.0, 0.0, 0.9647}, // blue
|
||||
{0.0, 0.9255, 0.9255}, // cyan
|
||||
{0.0, 0.5647, 0.0}, // dark green
|
||||
{0.0, 0.7843, 0.0}, // green
|
||||
{1.0, 1.0, 0.0}, // yellow
|
||||
{0.90588, 0.75294, 0.0}, // yellow-orange
|
||||
{1.0, 0.5647, 0.0}, // orange
|
||||
{1.0, 0.0, 0.0}, // bright red
|
||||
{0.8392, 0.0, 0.0}, // red
|
||||
{1.0, 0.0, 1.0}, // magenta
|
||||
{0.6, 0.3333, 0.7882}, // purple
|
||||
{1.0, 1.0, 1.0}, // white
|
||||
{1.0, 1.0, 1.0} // white
|
||||
};
|
||||
|
||||
// The 5th color in the array (cyan) represents middle gray (18%)
|
||||
// Every stop above or below middle gray causes a color shift
|
||||
float v = log2(dot(x, LUMA_REC709) / 0.18f);
|
||||
v = clamp(v + 5.0f, 0.0f, 15.0f);
|
||||
|
||||
size_t index = size_t(v);
|
||||
return mix(debugColors[index], debugColors[index + 1], saturate(v - float(index)));
|
||||
}
|
||||
|
||||
} // namespace tonemap
|
||||
} // namespace filament
|
||||
@@ -35,161 +35,7 @@ using namespace math;
|
||||
|
||||
namespace aces {
|
||||
|
||||
inline float rgb_2_saturation(float3 rgb) {
|
||||
// Input: ACES
|
||||
// Output: OCES
|
||||
constexpr float TINY = 1e-5f;
|
||||
float mi = min(rgb);
|
||||
float ma = max(rgb);
|
||||
return (max(ma, TINY) - max(mi, TINY)) / max(ma, 1e-2f);
|
||||
}
|
||||
|
||||
inline float rgb_2_yc(float3 rgb) {
|
||||
constexpr float ycRadiusWeight = 1.75f;
|
||||
|
||||
// Converts RGB to a luminance proxy, here called YC
|
||||
// YC is ~ Y + K * Chroma
|
||||
// Constant YC is a cone-shaped surface in RGB space, with the tip on the
|
||||
// neutral axis, towards white.
|
||||
// YC is normalized: RGB 1 1 1 maps to YC = 1
|
||||
//
|
||||
// ycRadiusWeight defaults to 1.75, although can be overridden in function
|
||||
// call to rgb_2_yc
|
||||
// ycRadiusWeight = 1 -> YC for pure cyan, magenta, yellow == YC for neutral
|
||||
// of same value
|
||||
// ycRadiusWeight = 2 -> YC for pure red, green, blue == YC for neutral of
|
||||
// same value.
|
||||
|
||||
float r = rgb.r;
|
||||
float g = rgb.g;
|
||||
float b = rgb.b;
|
||||
|
||||
float chroma = std::sqrt(b * (b - g) + g * (g - r) + r * (r - b));
|
||||
|
||||
return (b + g + r + ycRadiusWeight * chroma) / 3.0f;
|
||||
}
|
||||
|
||||
inline float sigmoid_shaper(float x) {
|
||||
// Sigmoid function in the range 0 to 1 spanning -2 to +2.
|
||||
float t = max(1.0f - std::abs(x / 2.0f), 0.0f);
|
||||
float y = 1.0f + sign(x) * (1.0f - t * t);
|
||||
return y / 2.0f;
|
||||
}
|
||||
|
||||
inline float glow_fwd(float ycIn, float glowGainIn, float glowMid) {
|
||||
float glowGainOut;
|
||||
|
||||
if (ycIn <= 2.0f / 3.0f * glowMid) {
|
||||
glowGainOut = glowGainIn;
|
||||
} else if ( ycIn >= 2.0f * glowMid) {
|
||||
glowGainOut = 0.0f;
|
||||
} else {
|
||||
glowGainOut = glowGainIn * (glowMid / ycIn - 1.0f / 2.0f);
|
||||
}
|
||||
|
||||
return glowGainOut;
|
||||
}
|
||||
|
||||
inline float rgb_2_hue(float3 rgb) {
|
||||
// Returns a geometric hue angle in degrees (0-360) based on RGB values.
|
||||
// For neutral colors, hue is undefined and the function will return a quiet NaN value.
|
||||
float hue = 0.0f;
|
||||
// RGB triplets where RGB are equal have an undefined hue
|
||||
if (!(rgb.x == rgb.y && rgb.y == rgb.z)) {
|
||||
hue = f::RAD_TO_DEG * std::atan2(
|
||||
std::sqrt(3.0f) * (rgb.y - rgb.z),
|
||||
2.0f * rgb.x - rgb.y - rgb.z);
|
||||
}
|
||||
return (hue < 0.0f) ? hue + 360.0f : hue;
|
||||
}
|
||||
|
||||
inline float center_hue(float hue, float centerH) {
|
||||
float hueCentered = hue - centerH;
|
||||
if (hueCentered < -180.0f) {
|
||||
hueCentered = hueCentered + 360.0f;
|
||||
} else if (hueCentered > 180.0f) {
|
||||
hueCentered = hueCentered - 360.0f;
|
||||
}
|
||||
return hueCentered;
|
||||
}
|
||||
|
||||
inline float3 darkSurround_to_dimSurround(float3 linearCV) {
|
||||
constexpr float DIM_SURROUND_GAMMA = 0.9811f;
|
||||
|
||||
float3 XYZ = AP1_to_XYZ * linearCV;
|
||||
float3 xyY = XYZ_to_xyY(XYZ);
|
||||
|
||||
xyY.z = clamp(xyY.z, 0.0f, (float)std::numeric_limits<math::half>::max());
|
||||
xyY.z = std::pow(xyY.z, DIM_SURROUND_GAMMA);
|
||||
|
||||
XYZ = xyY_to_XYZ(xyY);
|
||||
return XYZ_to_AP1 * XYZ;
|
||||
}
|
||||
|
||||
UTILS_ALWAYS_INLINE
|
||||
inline float3 ACES(float3 color, float brightness) {
|
||||
// Some bits were removed to adapt to our desired output
|
||||
// Input: ACEScg (AP1)
|
||||
// Output: ACEScg (AP1)
|
||||
|
||||
// "Glow" module constants
|
||||
constexpr float RRT_GLOW_GAIN = 0.05f;
|
||||
constexpr float RRT_GLOW_MID = 0.08f;
|
||||
|
||||
// Red modifier constants
|
||||
constexpr float RRT_RED_SCALE = 0.82f;
|
||||
constexpr float RRT_RED_PIVOT = 0.03f;
|
||||
constexpr float RRT_RED_HUE = 0.0f;
|
||||
constexpr float RRT_RED_WIDTH = 135.0f;
|
||||
|
||||
// Desaturation constants
|
||||
constexpr float RRT_SAT_FACTOR = 0.96f;
|
||||
constexpr float ODT_SAT_FACTOR = 0.93f;
|
||||
|
||||
float3 ap0 = AP1_to_AP0 * color;
|
||||
|
||||
// Glow module
|
||||
float saturation = rgb_2_saturation(ap0);
|
||||
float ycIn = rgb_2_yc(ap0);
|
||||
float s = sigmoid_shaper((saturation - 0.4f) / 0.2f);
|
||||
float addedGlow = 1.0f + glow_fwd(ycIn, RRT_GLOW_GAIN * s, RRT_GLOW_MID);
|
||||
ap0 *= addedGlow;
|
||||
|
||||
// Red modifier
|
||||
float hue = rgb_2_hue(ap0);
|
||||
float centeredHue = center_hue(hue, RRT_RED_HUE);
|
||||
float hueWeight = smoothstep(0.0f, 1.0f, 1.0f - std::abs(2.0f * centeredHue / RRT_RED_WIDTH));
|
||||
hueWeight *= hueWeight;
|
||||
|
||||
ap0.r += hueWeight * saturation * (RRT_RED_PIVOT - ap0.r) * (1.0f - RRT_RED_SCALE);
|
||||
|
||||
// ACES to RGB rendering space
|
||||
float3 ap1 = clamp(AP0_to_AP1 * ap0, 0.0f, (float) std::numeric_limits<math::half>::max());
|
||||
|
||||
// Global desaturation
|
||||
ap1 = mix(float3(dot(ap1, LUMA_AP1)), ap1, RRT_SAT_FACTOR);
|
||||
|
||||
// NOTE: This is specific to Filament and added only to match ACES to our legacy tone mapper
|
||||
// which was a fit of ACES in Rec.709 but with a brightness boost.
|
||||
ap1 *= brightness;
|
||||
|
||||
// Fitting of RRT + ODT (RGB monitor 100 nits dim) from:
|
||||
// https://github.com/colour-science/colour-unity/blob/master/Assets/Colour/Notebooks/CIECAM02_Unity.ipynb
|
||||
constexpr float a = 2.785085f;
|
||||
constexpr float b = 0.107772f;
|
||||
constexpr float c = 2.936045f;
|
||||
constexpr float d = 0.887122f;
|
||||
constexpr float e = 0.806889f;
|
||||
float3 rgbPost = (ap1 * (a * ap1 + b)) / (ap1 * (c * ap1 + d) + e);
|
||||
|
||||
// Apply gamma adjustment to compensate for dim surround
|
||||
float3 linearCV = darkSurround_to_dimSurround(rgbPost);
|
||||
|
||||
// Apply desaturation to compensate for luminance difference
|
||||
linearCV = mix(float3(dot(linearCV, LUMA_AP1)), linearCV, ODT_SAT_FACTOR);
|
||||
|
||||
return linearCV;
|
||||
}
|
||||
float3 ACES(float3 color, float brightness) noexcept;
|
||||
|
||||
} // namespace aces
|
||||
|
||||
@@ -217,42 +63,11 @@ constexpr float3 Filmic(float3 x) noexcept {
|
||||
return (x * (a * x + b)) / (x * (c * x + d) + e);
|
||||
}
|
||||
|
||||
float3 ACES(float3 x) noexcept {
|
||||
return aces::ACES(x, 1.0f);
|
||||
}
|
||||
float3 ACES(float3 x) noexcept;
|
||||
|
||||
float3 ACES_Legacy(float3 x) noexcept {
|
||||
return aces::ACES(x, 1.0f / 0.6f);
|
||||
}
|
||||
float3 ACES_Legacy(float3 x) noexcept;
|
||||
|
||||
float3 Uchimura(float3 x) {
|
||||
// Uchimura 2017, "HDR theory and practice"
|
||||
// Math: https://www.desmos.com/calculator/gslcdxvipg
|
||||
// Source: https://www.slideshare.net/nikuque/hdr-theory-and-practicce-jp
|
||||
|
||||
constexpr float P = 1.0; // max display brightness
|
||||
constexpr float a = 1.0; // contrast
|
||||
constexpr float m = 0.22; // linear section start
|
||||
constexpr float l = 0.4; // linear section length
|
||||
constexpr float c = 1.33; // black
|
||||
constexpr float b = 0.0; // pedestal
|
||||
|
||||
constexpr float l0 = ((P - m) * l) / a;
|
||||
constexpr float S0 = m + l0;
|
||||
constexpr float S1 = m + a * l0;
|
||||
constexpr float C2 = (a * P) / (P - S1);
|
||||
constexpr float CP = -C2 / P;
|
||||
|
||||
float3 w0 = 1.0f - smoothstep(0.0f, m, x);
|
||||
float3 w2 = step(m + l0, x);
|
||||
float3 w1 = 1.0f - w0 - w2;
|
||||
|
||||
float3 T = m * pow(x / m, c) + b;
|
||||
float3 S = P - (P - S1) * exp(CP * (x - S0));
|
||||
float3 L = m + a * (x - m);
|
||||
|
||||
return T * w0 + L * w1 + S * w2;
|
||||
}
|
||||
float3 Uchimura(float3 x) noexcept;
|
||||
|
||||
/**
|
||||
* Converts the input HDR RGB color into one of 16 debug colors that represent
|
||||
@@ -279,37 +94,7 @@ float3 Uchimura(float3 x) {
|
||||
* +9EV - purple
|
||||
* +10EV - white
|
||||
*/
|
||||
float3 DisplayRange(float3 x) noexcept {
|
||||
// 16 debug colors + 1 duplicated at the end for easy indexing
|
||||
|
||||
constexpr float3 debugColors[17] = {
|
||||
{0.0, 0.0, 0.0}, // black
|
||||
{0.0, 0.0, 0.1647}, // darkest blue
|
||||
{0.0, 0.0, 0.3647}, // darker blue
|
||||
{0.0, 0.0, 0.6647}, // dark blue
|
||||
{0.0, 0.0, 0.9647}, // blue
|
||||
{0.0, 0.9255, 0.9255}, // cyan
|
||||
{0.0, 0.5647, 0.0}, // dark green
|
||||
{0.0, 0.7843, 0.0}, // green
|
||||
{1.0, 1.0, 0.0}, // yellow
|
||||
{0.90588, 0.75294, 0.0}, // yellow-orange
|
||||
{1.0, 0.5647, 0.0}, // orange
|
||||
{1.0, 0.0, 0.0}, // bright red
|
||||
{0.8392, 0.0, 0.0}, // red
|
||||
{1.0, 0.0, 1.0}, // magenta
|
||||
{0.6, 0.3333, 0.7882}, // purple
|
||||
{1.0, 1.0, 1.0}, // white
|
||||
{1.0, 1.0, 1.0} // white
|
||||
};
|
||||
|
||||
// The 5th color in the array (cyan) represents middle gray (18%)
|
||||
// Every stop above or below middle gray causes a color shift
|
||||
float v = log2(dot(x, LUMA_REC709) / 0.18f);
|
||||
v = clamp(v + 5.0f, 0.0f, 15.0f);
|
||||
|
||||
size_t index = size_t(v);
|
||||
return mix(debugColors[index], debugColors[index + 1], saturate(v - float(index)));
|
||||
}
|
||||
float3 DisplayRange(float3 x) noexcept;
|
||||
|
||||
} // namespace tonemap
|
||||
|
||||
|
||||
@@ -90,6 +90,77 @@ void UniformBuffer::free(void* addr, size_t) noexcept {
|
||||
::free(addr);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
template<size_t Size>
|
||||
void UniformBuffer::setUniformUntyped(size_t offset, void const* UTILS_RESTRICT v) noexcept{
|
||||
setUniformUntyped<Size>(invalidateUniforms(offset, Size), 0ul, v);
|
||||
}
|
||||
|
||||
template
|
||||
void UniformBuffer::setUniformUntyped<4ul>(size_t offset, void const* UTILS_RESTRICT v) noexcept;
|
||||
template
|
||||
void UniformBuffer::setUniformUntyped<8ul>(size_t offset, void const* UTILS_RESTRICT v) noexcept;
|
||||
template
|
||||
void UniformBuffer::setUniformUntyped<12ul>(size_t offset, void const* UTILS_RESTRICT v) noexcept;
|
||||
template
|
||||
void UniformBuffer::setUniformUntyped<16ul>(size_t offset, void const* UTILS_RESTRICT v) noexcept;
|
||||
template
|
||||
void UniformBuffer::setUniformUntyped<64ul>(size_t offset, void const* UTILS_RESTRICT v) noexcept;
|
||||
|
||||
template<size_t Size>
|
||||
void UniformBuffer::setUniformArrayUntyped(size_t offset, void const* UTILS_RESTRICT begin, size_t count) noexcept {
|
||||
constexpr size_t stride = (Size + 0xFu) & ~0xFu;
|
||||
size_t arraySize = stride * count - stride + Size;
|
||||
void* UTILS_RESTRICT p = invalidateUniforms(offset, arraySize);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
setUniformUntyped<Size>(p, 0ul, static_cast<const char *>(begin) + i * Size);
|
||||
p = utils::pointermath::add(p, stride);
|
||||
}
|
||||
}
|
||||
|
||||
template
|
||||
void UniformBuffer::setUniformArrayUntyped<4ul>(size_t offset, void const* UTILS_RESTRICT begin, size_t count) noexcept;
|
||||
template
|
||||
void UniformBuffer::setUniformArrayUntyped<8ul>(size_t offset, void const* UTILS_RESTRICT begin, size_t count) noexcept;
|
||||
template
|
||||
void UniformBuffer::setUniformArrayUntyped<12ul>(size_t offset, void const* UTILS_RESTRICT begin, size_t count) noexcept;
|
||||
template
|
||||
void UniformBuffer::setUniformArrayUntyped<16ul>(size_t offset, void const* UTILS_RESTRICT begin, size_t count) noexcept;
|
||||
template
|
||||
void UniformBuffer::setUniformArrayUntyped<64ul>(size_t offset, void const* UTILS_RESTRICT begin, size_t count) noexcept;
|
||||
|
||||
// specialization for mat3f (which has a different alignment, see std140 layout rules)
|
||||
template<>
|
||||
UTILS_NOINLINE
|
||||
void UniformBuffer::setUniform(void* addr, size_t offset, const math::mat3f& v) noexcept {
|
||||
struct mat43 {
|
||||
float v[3][4];
|
||||
};
|
||||
|
||||
addr = static_cast<char*>(addr) + offset;
|
||||
mat43& temp = *static_cast<mat43*>(addr);
|
||||
|
||||
temp.v[0][0] = v[0][0];
|
||||
temp.v[0][1] = v[0][1];
|
||||
temp.v[0][2] = v[0][2];
|
||||
|
||||
temp.v[1][0] = v[1][0];
|
||||
temp.v[1][1] = v[1][1];
|
||||
temp.v[1][2] = v[1][2];
|
||||
|
||||
temp.v[2][0] = v[2][0];
|
||||
temp.v[2][1] = v[2][1];
|
||||
temp.v[2][2] = v[2][2];
|
||||
|
||||
// don't store anything in temp.v[][3] because there could be uniforms packed there
|
||||
}
|
||||
|
||||
template<>
|
||||
void UniformBuffer::setUniform(size_t offset, const math::mat3f& v) noexcept {
|
||||
setUniform(invalidateUniforms(offset, sizeof(v)), 0, v);
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
|
||||
utils::io::ostream& operator<<(utils::io::ostream& out, const UniformBuffer& rhs) {
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <math/mat4.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
@@ -94,17 +95,15 @@ public:
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
|
||||
// Note: we purposedly not include types that require conversion here
|
||||
// (e.g. bool and bool vectors)
|
||||
template <typename T>
|
||||
struct is_supported_type {
|
||||
using type = typename std::enable_if<
|
||||
std::is_same<bool, T>::value ||
|
||||
std::is_same<float, T>::value ||
|
||||
std::is_same<int32_t, T>::value ||
|
||||
std::is_same<uint32_t, T>::value ||
|
||||
std::is_same<math::quatf, T>::value ||
|
||||
std::is_same<math::bool2, T>::value ||
|
||||
std::is_same<math::bool3, T>::value ||
|
||||
std::is_same<math::bool4, T>::value ||
|
||||
std::is_same<math::int2, T>::value ||
|
||||
std::is_same<math::int3, T>::value ||
|
||||
std::is_same<math::int4, T>::value ||
|
||||
@@ -132,34 +131,32 @@ public:
|
||||
// a x x x b x x x c
|
||||
//
|
||||
// The "x" symbols represent dummy words.
|
||||
template <typename T, typename = typename is_supported_type<T>::type>
|
||||
template<typename T, typename = typename is_supported_type<T>::type>
|
||||
UTILS_ALWAYS_INLINE
|
||||
void setUniformArray(size_t offset, T const* UTILS_RESTRICT begin, size_t count) noexcept {
|
||||
constexpr size_t stride = (sizeof(T) + 0xFu) & ~0xFu;
|
||||
size_t arraySize = stride * count - stride + sizeof(T);
|
||||
T* UTILS_RESTRICT p = static_cast<T*>(invalidateUniforms(offset, arraySize));
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
*p = begin[i];
|
||||
p = utils::pointermath::add(p, stride);
|
||||
}
|
||||
static_assert(!std::is_same_v<T, math::mat3f>);
|
||||
setUniformArrayUntyped<sizeof(T)>(offset, begin, count);
|
||||
}
|
||||
|
||||
// (see specialization for mat3f below)
|
||||
template <typename T, typename = typename is_supported_type<T>::type>
|
||||
static void setUniform(void* addr, size_t offset, const T& v) noexcept {
|
||||
addr = static_cast<char*>(addr) + offset;
|
||||
T* p = static_cast<T*>(addr);
|
||||
*p = v;
|
||||
template<typename T, typename = typename is_supported_type<T>::type>
|
||||
UTILS_ALWAYS_INLINE
|
||||
static inline void setUniform(void* addr, size_t offset, const T& v) noexcept {
|
||||
static_assert(!std::is_same_v<T, math::mat3f>);
|
||||
setUniformUntyped<sizeof(T)>(addr, offset, &v);
|
||||
}
|
||||
|
||||
// set uniform of known types to the proper offset (e.g.: use offsetof())
|
||||
template <typename T, typename = typename is_supported_type<T>::type>
|
||||
void setUniform(size_t offset, const T& v) noexcept {
|
||||
setUniform(invalidateUniforms(offset, sizeof(T)), 0, v);
|
||||
template<typename T, typename = typename is_supported_type<T>::type>
|
||||
UTILS_ALWAYS_INLINE
|
||||
inline void setUniform(size_t offset, const T& v) noexcept {
|
||||
static_assert(!std::is_same_v<T, math::mat3f>);
|
||||
setUniformUntyped<sizeof(T)>(offset, &v);
|
||||
}
|
||||
|
||||
// get uniform of known types from the proper offset (e.g.: use offsetof())
|
||||
template<typename T, typename = typename is_supported_type<T>::type>
|
||||
T getUniform(size_t offset) const noexcept {
|
||||
static_assert(!std::is_same_v<T, math::mat3f>);
|
||||
return *reinterpret_cast<T const*>(static_cast<char const*>(mBuffer) + offset);
|
||||
}
|
||||
|
||||
@@ -175,11 +172,18 @@ public:
|
||||
backend::BufferDescriptor p;
|
||||
p.size = size;
|
||||
p.buffer = driver.allocate(p.size); // TODO: use out-of-line buffer if too large
|
||||
memcpy(p.buffer, static_cast<const char*>(getBuffer()) + offset, p.size);
|
||||
memcpy(p.buffer, static_cast<const char*>(getBuffer()) + offset, p.size); // inlined
|
||||
clean();
|
||||
return p;
|
||||
}
|
||||
|
||||
// set uniform of known types to the proper offset (e.g.: use offsetof())
|
||||
template<size_t Size>
|
||||
void setUniformUntyped(size_t offset, void const* UTILS_RESTRICT v) noexcept;
|
||||
|
||||
template<size_t Size>
|
||||
void setUniformArrayUntyped(size_t offset, void const* UTILS_RESTRICT begin, size_t count) noexcept;
|
||||
|
||||
private:
|
||||
#if !defined(NDEBUG)
|
||||
friend utils::io::ostream& operator<<(utils::io::ostream& out, const UniformBuffer& rhs);
|
||||
@@ -187,9 +191,16 @@ private:
|
||||
static void* alloc(size_t size) noexcept;
|
||||
static void free(void* addr, size_t size) noexcept;
|
||||
|
||||
template<size_t Size, std::enable_if_t<
|
||||
Size == 4 || Size == 8 || Size == 12 || Size == 16 || Size == 64, bool> = true>
|
||||
UTILS_ALWAYS_INLINE
|
||||
static void setUniformUntyped(void* addr, size_t offset, void const* v) noexcept {
|
||||
memcpy(static_cast<char*>(addr) + offset, v, Size); // inlined
|
||||
}
|
||||
|
||||
inline bool isLocalStorage() const noexcept { return mBuffer == mStorage; }
|
||||
|
||||
// TODO: we need a better to calculate this local storage.
|
||||
// TODO: we need a better way to calculate this local storage.
|
||||
// Probably the better thing to do would be to use a special allocator.
|
||||
// Local storage is limited by the total size of a handle (128 byte for GL)
|
||||
char mStorage[96];
|
||||
@@ -200,28 +211,16 @@ private:
|
||||
|
||||
// specialization for mat3f (which has a different alignment, see std140 layout rules)
|
||||
template<>
|
||||
inline void UniformBuffer::setUniform(void* addr, size_t offset, const math::mat3f& v) noexcept {
|
||||
struct mat43 {
|
||||
float v[3][4];
|
||||
};
|
||||
void UniformBuffer::setUniform(void* addr, size_t offset, const math::mat3f& v) noexcept;
|
||||
|
||||
addr = static_cast<char*>(addr) + offset;
|
||||
mat43& temp = *static_cast<mat43*>(addr);
|
||||
template<>
|
||||
void UniformBuffer::setUniform(size_t offset, const math::mat3f& v) noexcept;
|
||||
|
||||
temp.v[0][0] = v[0][0];
|
||||
temp.v[0][1] = v[0][1];
|
||||
temp.v[0][2] = v[0][2];
|
||||
temp.v[0][3] = 0; // not needed, but doesn't cost anything
|
||||
|
||||
temp.v[1][0] = v[1][0];
|
||||
temp.v[1][1] = v[1][1];
|
||||
temp.v[1][2] = v[1][2];
|
||||
temp.v[1][3] = 0; // not needed, but doesn't cost anything
|
||||
|
||||
temp.v[2][0] = v[2][0];
|
||||
temp.v[2][1] = v[2][1];
|
||||
temp.v[2][2] = v[2][2];
|
||||
temp.v[2][3] = 0; // not needed, but doesn't cost anything
|
||||
template<>
|
||||
inline void UniformBuffer::setUniformArray(
|
||||
size_t offset, math::mat3f const* UTILS_RESTRICT begin, size_t count) noexcept {
|
||||
// pretend each mat3 is an array of 3 float3
|
||||
setUniformArray(offset, reinterpret_cast<math::float3 const*>(begin), count * 3);
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -231,13 +230,6 @@ inline math::mat3f UniformBuffer::getUniform(size_t offset) const noexcept {
|
||||
return { p[0].xyz, p[1].xyz, p[2].xyz };
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void UniformBuffer::setUniformArray(
|
||||
size_t offset, math::mat3f const* UTILS_RESTRICT begin, size_t count) noexcept {
|
||||
// pretend each mat3 is an array of 3 float3
|
||||
setUniformArray(offset, reinterpret_cast<math::float3 const*>(begin), count * 3);
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_UNIFORMBUFFER_H
|
||||
|
||||
@@ -60,18 +60,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename = is_supported_parameter_t<T>>
|
||||
void setParameter(const char* name, T value) noexcept;
|
||||
|
||||
template <typename T, typename = is_supported_parameter_t<T>>
|
||||
void setParameter(const char* name, const T* value, size_t count) noexcept;
|
||||
|
||||
void setParameter(const char* name,
|
||||
Texture const* texture, TextureSampler const& sampler) noexcept;
|
||||
|
||||
void setParameter(const char* name,
|
||||
backend::Handle<backend::HwTexture> texture, backend::SamplerParams params) noexcept;
|
||||
|
||||
FMaterial const* getMaterial() const noexcept { return mMaterial; }
|
||||
|
||||
uint64_t getSortingKey() const noexcept { return mMaterialSortingKey; }
|
||||
@@ -110,34 +98,48 @@ public:
|
||||
|
||||
backend::PolygonOffset getPolygonOffset() const noexcept { return mPolygonOffset; }
|
||||
|
||||
void setMaskThreshold(float threshold) noexcept {
|
||||
setParameter("_maskThreshold", math::saturate(threshold));
|
||||
}
|
||||
void setMaskThreshold(float threshold) noexcept;
|
||||
|
||||
void setSpecularAntiAliasingVariance(float variance) noexcept {
|
||||
setParameter("_specularAntiAliasingVariance", math::saturate(variance));
|
||||
}
|
||||
void setSpecularAntiAliasingVariance(float variance) noexcept;
|
||||
|
||||
void setSpecularAntiAliasingThreshold(float threshold) noexcept {
|
||||
setParameter("_specularAntiAliasingThreshold", math::saturate(threshold * threshold));
|
||||
}
|
||||
void setSpecularAntiAliasingThreshold(float threshold) noexcept;
|
||||
|
||||
void setDoubleSided(bool doubleSided) noexcept;
|
||||
|
||||
void setCullingMode(CullingMode culling) noexcept;
|
||||
void setCullingMode(CullingMode culling) noexcept { mCulling = culling; }
|
||||
|
||||
void setColorWrite(bool enable) noexcept;
|
||||
void setColorWrite(bool enable) noexcept { mColorWrite = enable; }
|
||||
|
||||
void setDepthWrite(bool enable) noexcept;
|
||||
void setDepthWrite(bool enable) noexcept { mDepthWrite = enable; }
|
||||
|
||||
void setDepthCulling(bool enable) noexcept;
|
||||
|
||||
const char* getName() const noexcept;
|
||||
|
||||
void setParameter(const char* name,
|
||||
backend::Handle<backend::HwTexture> texture, backend::SamplerParams params) noexcept;
|
||||
|
||||
using MaterialInstance::setParameter;
|
||||
|
||||
private:
|
||||
friend class FMaterial;
|
||||
friend class MaterialInstance;
|
||||
|
||||
template<size_t Size>
|
||||
void setParameterUntypedImpl(const char* name, const void* value) noexcept;
|
||||
|
||||
template<size_t Size>
|
||||
void setParameterUntypedImpl(const char* name, const void* value, size_t count) noexcept;
|
||||
|
||||
template<typename T>
|
||||
void setParameterImpl(const char* name, T const& value) noexcept;
|
||||
|
||||
template<typename T>
|
||||
void setParameterImpl(const char* name, const T* value, size_t count) noexcept;
|
||||
|
||||
void setParameterImpl(const char* name,
|
||||
Texture const* texture, TextureSampler const& sampler) noexcept;
|
||||
|
||||
FMaterialInstance() noexcept;
|
||||
void initDefaultInstance(FEngine& engine, FMaterial const* material);
|
||||
void initialize(FMaterial const* material);
|
||||
|
||||
@@ -63,8 +63,9 @@ DependencyGraph::EdgeContainer DependencyGraph::getIncomingEdges(
|
||||
// TODO: we might need something more efficient
|
||||
EdgeContainer result;
|
||||
result.reserve(mEdges.size());
|
||||
NodeID const nodeId = node->getId();
|
||||
for (auto* edge : mEdges) {
|
||||
if (edge->to == node->getId()) {
|
||||
if (edge->to == nodeId) {
|
||||
result.push_back(edge);
|
||||
}
|
||||
}
|
||||
@@ -76,8 +77,9 @@ DependencyGraph::EdgeContainer DependencyGraph::getOutgoingEdges(
|
||||
// TODO: we might need something more efficient
|
||||
EdgeContainer result;
|
||||
result.reserve(mEdges.size());
|
||||
NodeID const nodeId = node->getId();
|
||||
for (auto* edge : mEdges) {
|
||||
if (edge->from == node->getId()) {
|
||||
if (edge->from == nodeId) {
|
||||
result.push_back(edge);
|
||||
}
|
||||
}
|
||||
@@ -235,23 +237,11 @@ uint32_t DependencyGraph::Node::getRefCount() const noexcept {
|
||||
return (mRefCount & TARGET) ? 1u : mRefCount;
|
||||
}
|
||||
|
||||
uint32_t DependencyGraph::Node::getId() const noexcept {
|
||||
return mId;
|
||||
}
|
||||
|
||||
bool DependencyGraph::Node::isCulled() const noexcept {
|
||||
return mRefCount == 0;
|
||||
}
|
||||
|
||||
void DependencyGraph::Node::makeTarget() noexcept {
|
||||
assert_invariant(mRefCount == 0 || mRefCount == TARGET);
|
||||
mRefCount = TARGET;
|
||||
}
|
||||
|
||||
bool DependencyGraph::Node::isTarget() const noexcept {
|
||||
return mRefCount >= TARGET;
|
||||
}
|
||||
|
||||
char const* DependencyGraph::Node::getName() const noexcept {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
@@ -86,20 +86,20 @@ public:
|
||||
virtual ~Node() noexcept = default;
|
||||
|
||||
//! returns a unique id for this node
|
||||
NodeID getId() const noexcept;
|
||||
NodeID getId() const noexcept { return mId; }
|
||||
|
||||
/** Prevents this node from being culled. Must be called before culling. */
|
||||
void makeTarget() noexcept;
|
||||
|
||||
/** Returns true if this Node is a target */
|
||||
bool isTarget() const noexcept;
|
||||
bool isTarget() const noexcept { return mRefCount >= TARGET; }
|
||||
|
||||
/**
|
||||
* Returns whether this node was culled.
|
||||
* This is only valid after DependencyGraph::cull() has been called.
|
||||
* @return true if the node has been culled, false otherwise.
|
||||
*/
|
||||
bool isCulled() const noexcept;
|
||||
bool isCulled() const noexcept { return mRefCount == 0; }
|
||||
|
||||
/**
|
||||
* return the reference count of this node. That is how many other nodes have links to us.
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
|
||||
ChunkContainer(void const* data, size_t size) : mData(data), mSize(size) {}
|
||||
|
||||
~ChunkContainer() = default;
|
||||
~ChunkContainer() noexcept;
|
||||
|
||||
// Must be called before trying to access any of the chunk. Fails and return false ONLY if
|
||||
// an incomplete chunk is found or if a chunk with bogus size is found.
|
||||
@@ -66,11 +66,20 @@ public:
|
||||
}
|
||||
|
||||
const uint8_t* getChunkEnd(Type type) const noexcept {
|
||||
return mChunks.at(type).start + mChunks.at(type).size;
|
||||
ChunkDesc const& chunkDesc = mChunks.at(type);
|
||||
return chunkDesc.start + chunkDesc.size;
|
||||
}
|
||||
|
||||
bool hasChunk(Type type) const noexcept {
|
||||
return mChunks.find(type) != mChunks.end();
|
||||
bool hasChunk(Type type, ChunkDesc const** pChunkDesc = nullptr) const noexcept {
|
||||
auto& chunks = mChunks;
|
||||
auto pos = chunks.find(type);
|
||||
if (pos != chunks.end()) {
|
||||
if (pChunkDesc) {
|
||||
*pChunkDesc = &pos.value();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void const* getData() const { return mData; }
|
||||
|
||||
@@ -33,6 +33,7 @@ class ShaderBuilder;
|
||||
class MaterialChunk {
|
||||
public:
|
||||
explicit MaterialChunk(ChunkContainer const& container);
|
||||
~MaterialChunk() noexcept;
|
||||
|
||||
// call this once after container.parse() has been called
|
||||
bool readIndex(filamat::ChunkType materialTag);
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
namespace filaflat {
|
||||
|
||||
ChunkContainer::~ChunkContainer() noexcept = default;
|
||||
|
||||
bool ChunkContainer::parseChunk(Unflattener& unflattener) {
|
||||
uint64_t type;
|
||||
if (!unflattener.read(&type)) {
|
||||
|
||||
@@ -31,6 +31,8 @@ MaterialChunk::MaterialChunk(ChunkContainer const& container)
|
||||
: mContainer(container) {
|
||||
}
|
||||
|
||||
MaterialChunk::~MaterialChunk() noexcept = default;
|
||||
|
||||
bool MaterialChunk::readIndex(filamat::ChunkType materialTag) {
|
||||
|
||||
if (mBase != nullptr) {
|
||||
|
||||
@@ -537,10 +537,10 @@ public:
|
||||
// construct an arena with a name and forward argument to its allocator
|
||||
template<typename ... ARGS>
|
||||
Arena(const char* name, size_t size, ARGS&& ... args)
|
||||
: mArea(size),
|
||||
: mArenaName(name),
|
||||
mArea(size),
|
||||
mAllocator(mArea, std::forward<ARGS>(args) ... ),
|
||||
mListener(name, mArea.data(), size),
|
||||
mArenaName(name) {
|
||||
mListener(name, mArea.data(), size) {
|
||||
}
|
||||
|
||||
// allocate memory from arena with given size and alignment
|
||||
@@ -647,11 +647,12 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
char const* mArenaName = nullptr;
|
||||
HeapArea mArea; // We might want to make that a template parameter too eventually.
|
||||
// note: we should use something like compressed_pair for the members below
|
||||
AllocatorPolicy mAllocator;
|
||||
LockingPolicy mLock;
|
||||
TrackingPolicy mListener;
|
||||
char const* mArenaName = nullptr;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user