Dynamic "Material constants" support
Material constants (a.k.a: specialization constants) can only be set during Material creation through Material::Builder. This change somewhat relaxes that limitation by allowing constants to be set at runtime on Material directly. Currently this new API is still private and only supported on FMaterial. This feature works by invalidating the HwProgram cache of the concerned Material, causing a shader recompile per variant; so this API is costly and should be used only for debugging or during app/game configuration. The TAA material is modified to use constants instead of #defines for various settings and those are exposed in TaaOptions as well is in ViewerGui. So with this change all aspects of the TAA material can be changed at runtime.
This commit is contained in:
committed by
Mathias Agopian
parent
2f62978e4c
commit
2a67152dda
@@ -1876,11 +1876,44 @@ public class View {
|
||||
|
||||
/**
|
||||
* Options for Temporal Anti-aliasing (TAA)
|
||||
* Most TAA parameters are extremely costly to change, as they will trigger the TAA post-process
|
||||
* shaders to be recompiled. These options should be changed or set during initialization.
|
||||
* `filterWidth` and `feedback`, however, could be changed an any time.
|
||||
* @see setTemporalAntiAliasingOptions()
|
||||
*/
|
||||
public static class TemporalAntiAliasingOptions {
|
||||
public enum BoxType {
|
||||
/**
|
||||
* use an AABB neighborhood
|
||||
*/
|
||||
AABB,
|
||||
/**
|
||||
* use the variance of the neighborhood
|
||||
*/
|
||||
VARIANCE,
|
||||
/**
|
||||
* use both AABB and variance
|
||||
*/
|
||||
AABB_VARIANCE,
|
||||
}
|
||||
|
||||
public enum BoxClipping {
|
||||
/**
|
||||
* Accurate box clipping
|
||||
*/
|
||||
ACCURATE,
|
||||
/**
|
||||
* clamping
|
||||
*/
|
||||
CLAMP,
|
||||
/**
|
||||
* no rejections (use for debugging)
|
||||
*/
|
||||
NONE,
|
||||
}
|
||||
|
||||
/**
|
||||
* reconstruction filter width typically between 0 (sharper, aliased) and 1 (smoother)
|
||||
* reconstruction filter width typically between 0.2 (sharper, aliased) and 1 (smoother)
|
||||
*/
|
||||
public float filterWidth = 1.0f;
|
||||
/**
|
||||
@@ -1891,6 +1924,36 @@ public class View {
|
||||
* enables or disables temporal anti-aliasing
|
||||
*/
|
||||
public boolean enabled = false;
|
||||
/**
|
||||
* whether to filter the history buffer
|
||||
*/
|
||||
public boolean filterHistory = true;
|
||||
/**
|
||||
* whether to apply the reconstruction filter to the input
|
||||
*/
|
||||
public boolean filterInput = true;
|
||||
/**
|
||||
* whether to use the YcoCg color-space for history rejection
|
||||
*/
|
||||
public boolean useYCoCg = false;
|
||||
/**
|
||||
* type of color gamut box
|
||||
*/
|
||||
@NonNull
|
||||
public TemporalAntiAliasingOptions.BoxType boxType = TemporalAntiAliasingOptions.BoxType.VARIANCE;
|
||||
/**
|
||||
* clipping algorithm
|
||||
*/
|
||||
@NonNull
|
||||
public TemporalAntiAliasingOptions.BoxClipping boxClipping = TemporalAntiAliasingOptions.BoxClipping.ACCURATE;
|
||||
/**
|
||||
* adjust the feedback dynamically to reduce flickering
|
||||
*/
|
||||
public boolean preventFlickering = false;
|
||||
/**
|
||||
* whether to apply history reprojection (debug option)
|
||||
*/
|
||||
public boolean historyReprojection = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+18
-7
File diff suppressed because one or more lines are too long
Binary file not shown.
+14
-1
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -587,6 +587,7 @@
|
||||
<li><em>overrides</em> Dictionary with one or more of the following properties: mapSize, shadowCascades, constantBias, normalBias, shadowFar, shadowNearHint, shadowFarHint, stable, polygonOffsetConstant, polygonOffsetSlope, \</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>engine.setStereoscopicOptions()</strong></li>
|
||||
<li><strong>engine.setTemporalAntiAliasingOptions()</strong></li>
|
||||
<li><strong>engine.setVignetteOptions()</strong></li>
|
||||
</ul>
|
||||
@@ -1462,6 +1463,8 @@ This defines the following functions:</p>
|
||||
<li>STENCIL_ATTACHMENT</li>
|
||||
<li>UPLOADABLE</li>
|
||||
<li>SAMPLEABLE</li>
|
||||
<li>BLIT_SRC</li>
|
||||
<li>BLIT_DST</li>
|
||||
<li>SUBPASS_INPUT</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -537,7 +537,7 @@ void OpenGLDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {
|
||||
|
||||
|
||||
if (UTILS_UNLIKELY(mContext.isES2())) {
|
||||
// Here we patch the specification constants to enable or not the rec709 output
|
||||
// Here we patch the specialization constants to enable or not the rec709 output
|
||||
// color space emulation in this program. Obviously, the backend shouldn't know about
|
||||
// specific spec-constants, so we need to handle failures gracefully. This cannot be
|
||||
// done at Material creation time because only the backend has access to
|
||||
|
||||
@@ -547,7 +547,8 @@ void ShaderCompilerService::compileShaders(OpenGLContext& context,
|
||||
// add support for ARB_shading_language_packing if needed
|
||||
auto const packingFunctions = process_ARB_shading_language_packing(context);
|
||||
|
||||
// split shader source, so we can insert the specification constants and the packing functions
|
||||
// split shader source, so we can insert the specialization constants and the packing
|
||||
// functions
|
||||
auto const [prolog, body] = splitShaderSource(source);
|
||||
|
||||
const std::array<const char*, 4> sources = {
|
||||
|
||||
@@ -424,12 +424,36 @@ struct MultiSampleAntiAliasingOptions {
|
||||
|
||||
/**
|
||||
* Options for Temporal Anti-aliasing (TAA)
|
||||
* Most TAA parameters are extremely costly to change, as they will trigger the TAA post-process
|
||||
* shaders to be recompiled. These options should be changed or set during initialization.
|
||||
* `filterWidth` and `feedback`, however, could be changed an any time.
|
||||
* @see setTemporalAntiAliasingOptions()
|
||||
*/
|
||||
struct TemporalAntiAliasingOptions {
|
||||
float filterWidth = 1.0f; //!< reconstruction filter width typically between 0 (sharper, aliased) and 1 (smoother)
|
||||
float filterWidth = 1.0f; //!< reconstruction filter width typically between 0.2 (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
|
||||
|
||||
enum class BoxType : uint8_t {
|
||||
AABB, //!< use an AABB neighborhood
|
||||
VARIANCE, //!< use the variance of the neighborhood
|
||||
AABB_VARIANCE //!< use both AABB and variance
|
||||
};
|
||||
|
||||
enum class BoxClipping : uint8_t {
|
||||
ACCURATE, //!< Accurate box clipping
|
||||
CLAMP, //!< clamping
|
||||
NONE //!< no rejections (use for debugging)
|
||||
};
|
||||
|
||||
bool filterHistory = true; //!< whether to filter the history buffer
|
||||
bool filterInput = true; //!< whether to apply the reconstruction filter to the input
|
||||
bool useYCoCg = false; //!< whether to use the YcoCg color-space for history rejection
|
||||
BoxType boxType = BoxType::VARIANCE; //!< type of color gamut box
|
||||
BoxClipping boxClipping = BoxClipping::ACCURATE; //!< clipping algorithm
|
||||
|
||||
bool preventFlickering = false; //!< adjust the feedback dynamically to reduce flickering
|
||||
bool historyReprojection = true; //!< whether to apply history reprojection (debug option)
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
#include <math/half.h>
|
||||
#include <math/mat2.h>
|
||||
|
||||
#include <utils/BitmaskEnum.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
@@ -200,7 +202,8 @@ void PostProcessManager::registerPostProcessMaterial(std::string_view name, Mate
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
PostProcessManager::PostProcessMaterial& PostProcessManager::getPostProcessMaterial(std::string_view name) noexcept {
|
||||
PostProcessManager::PostProcessMaterial& PostProcessManager::getPostProcessMaterial(
|
||||
std::string_view name) noexcept {
|
||||
assert_invariant(mMaterialRegistry.find(name) != mMaterialRegistry.end());
|
||||
return mMaterialRegistry[name];
|
||||
}
|
||||
@@ -2528,6 +2531,36 @@ void PostProcessManager::prepareTaa(FrameGraph& fg, filament::Viewport const& sv
|
||||
});
|
||||
}
|
||||
|
||||
void PostProcessManager::configureTemporalAntiAliasingMaterial(
|
||||
TemporalAntiAliasingOptions const& taaOptions) noexcept {
|
||||
|
||||
FMaterial* const ma = getPostProcessMaterial("taa").getMaterial(mEngine);
|
||||
bool dirty = false;
|
||||
|
||||
auto setConstantParameter =
|
||||
[&dirty](FMaterial* const ma, std::string_view name, auto value) noexcept {
|
||||
auto id = ma->getSpecializationConstantId(name);
|
||||
if (id.has_value()) {
|
||||
if (ma->setConstant(id.value(), value)) {
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
setConstantParameter(ma, "historyReprojection", taaOptions.historyReprojection);
|
||||
setConstantParameter(ma, "filterHistory", taaOptions.filterHistory);
|
||||
setConstantParameter(ma, "filterInput", taaOptions.filterInput);
|
||||
setConstantParameter(ma, "useYCoCg", taaOptions.useYCoCg);
|
||||
setConstantParameter(ma, "preventFlickering", taaOptions.preventFlickering);
|
||||
setConstantParameter(ma, "boxType", (int32_t)taaOptions.boxType);
|
||||
setConstantParameter(ma, "boxClipping", (int32_t)taaOptions.boxClipping);
|
||||
if (dirty) {
|
||||
ma->invalidate();
|
||||
// TODO: call Material::compile(), we can't si that now because it works only
|
||||
// with surface materials
|
||||
}
|
||||
}
|
||||
|
||||
FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> input,
|
||||
FrameGraphId<FrameGraphTexture> depth,
|
||||
@@ -2616,8 +2649,8 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
|
||||
auto color = resources.getTexture(data.color);
|
||||
auto depth = resources.getTexture(data.depth);
|
||||
auto history = resources.getTexture(data.history);
|
||||
|
||||
auto const& material = getPostProcessMaterial("taa");
|
||||
|
||||
FMaterialInstance* mi = material.getMaterialInstance(mEngine);
|
||||
mi->setParameter("color", color, {}); // nearest
|
||||
mi->setParameter("depth", depth, {}); // nearest
|
||||
|
||||
@@ -86,6 +86,10 @@ public:
|
||||
void init() noexcept;
|
||||
void terminate(backend::DriverApi& driver) noexcept;
|
||||
|
||||
|
||||
void configureTemporalAntiAliasingMaterial(
|
||||
TemporalAntiAliasingOptions const& taaOptions) noexcept;
|
||||
|
||||
// methods below are ordered relative to their position in the pipeline (as much as possible)
|
||||
|
||||
// structure (depth) pass
|
||||
|
||||
@@ -373,8 +373,13 @@ void FEngine::init() {
|
||||
|
||||
mDebugRegistry.registerProperty("d.shadowmap.debug_directional_shadowmap",
|
||||
&debug.shadowmap.debug_directional_shadowmap, [this]() {
|
||||
mMaterials.forEach([](FMaterial* material) {
|
||||
mMaterials.forEach([this](FMaterial* material) {
|
||||
if (material->getMaterialDomain() == MaterialDomain::SURFACE) {
|
||||
|
||||
material->setConstant(
|
||||
+ReservedSpecializationConstants::CONFIG_DEBUG_DIRECTIONAL_SHADOWMAP,
|
||||
debug.shadowmap.debug_directional_shadowmap);
|
||||
|
||||
material->invalidate(
|
||||
Variant::DIR | Variant::SRE | Variant::DEP,
|
||||
Variant::DIR | Variant::SRE);
|
||||
@@ -384,8 +389,13 @@ void FEngine::init() {
|
||||
|
||||
mDebugRegistry.registerProperty("d.lighting.debug_froxel_visualization",
|
||||
&debug.lighting.debug_froxel_visualization, [this]() {
|
||||
mMaterials.forEach([](FMaterial* material) {
|
||||
mMaterials.forEach([this](FMaterial* material) {
|
||||
if (material->getMaterialDomain() == MaterialDomain::SURFACE) {
|
||||
|
||||
material->setConstant(
|
||||
+ReservedSpecializationConstants::CONFIG_DEBUG_FROXEL_VISUALIZATION,
|
||||
debug.lighting.debug_froxel_visualization);
|
||||
|
||||
material->invalidate(
|
||||
Variant::DYN | Variant::DEP,
|
||||
Variant::DYN);
|
||||
|
||||
@@ -79,7 +79,10 @@ struct Material::BuilderDetails {
|
||||
size_t mSize = 0;
|
||||
MaterialParser* mMaterialParser = nullptr;
|
||||
bool mDefaultMaterial = false;
|
||||
std::unordered_map<std::string, std::variant<int32_t, float, bool>> mConstantSpecializations;
|
||||
std::unordered_map<
|
||||
utils::CString,
|
||||
std::variant<int32_t, float, bool>,
|
||||
CString::Hasher> mConstantSpecializations;
|
||||
};
|
||||
|
||||
FMaterial::DefaultMaterialBuilder::DefaultMaterialBuilder() : Material::Builder() {
|
||||
@@ -216,9 +219,14 @@ FMaterial::FMaterial(FEngine& engine, const Material::Builder& builder)
|
||||
mSubpassInfo.isValid = false;
|
||||
}
|
||||
|
||||
utils::FixedCapacityVector<MaterialConstant> constants;
|
||||
// Older materials won't have a constants chunk, but that's okay.
|
||||
parser->getConstants(&constants);
|
||||
parser->getConstants(&mMaterialConstants);
|
||||
for (size_t i = 0, c = mMaterialConstants.size(); i < c; i++) {
|
||||
auto& item = mMaterialConstants[i];
|
||||
// the key can be a string_view because mMaterialConstant owns the CString
|
||||
std::string_view const key{ item.name.data(), item.name.size() };
|
||||
mSpecializationConstantsNameToIndex[key] = i;
|
||||
}
|
||||
|
||||
// Verify that all the constant specializations exist in the material and that their types match.
|
||||
// The first specialization constants are defined internally by Filament.
|
||||
@@ -238,7 +246,7 @@ FMaterial::FMaterial(FEngine& engine, const Material::Builder& builder)
|
||||
bool const powerVrShaderWorkarounds =
|
||||
engine.getDriverApi().isWorkaroundNeeded(Workaround::POWER_VR_SHADER_WORKAROUNDS);
|
||||
|
||||
mSpecializationConstants.reserve(constants.size() + CONFIG_MAX_RESERVED_SPEC_CONSTANTS);
|
||||
mSpecializationConstants.reserve(mMaterialConstants.size() + CONFIG_MAX_RESERVED_SPEC_CONSTANTS);
|
||||
mSpecializationConstants.push_back({
|
||||
+ReservedSpecializationConstants::BACKEND_FEATURE_LEVEL,
|
||||
(int)engine.getSupportedFeatureLevel() });
|
||||
@@ -250,16 +258,16 @@ FMaterial::FMaterial(FEngine& engine, const Material::Builder& builder)
|
||||
(int)maxFroxelBufferHeight });
|
||||
mSpecializationConstants.push_back({
|
||||
+ReservedSpecializationConstants::CONFIG_DEBUG_DIRECTIONAL_SHADOWMAP,
|
||||
(bool)engine.debug.shadowmap.debug_directional_shadowmap });
|
||||
engine.debug.shadowmap.debug_directional_shadowmap });
|
||||
mSpecializationConstants.push_back({
|
||||
+ReservedSpecializationConstants::CONFIG_DEBUG_FROXEL_VISUALIZATION,
|
||||
(bool)engine.debug.lighting.debug_froxel_visualization });
|
||||
engine.debug.lighting.debug_froxel_visualization });
|
||||
mSpecializationConstants.push_back({
|
||||
+ReservedSpecializationConstants::CONFIG_STATIC_TEXTURE_TARGET_WORKAROUND,
|
||||
(bool)staticTextureWorkaround });
|
||||
staticTextureWorkaround });
|
||||
mSpecializationConstants.push_back({
|
||||
+ReservedSpecializationConstants::CONFIG_POWER_VR_SHADER_WORKAROUNDS,
|
||||
(bool)powerVrShaderWorkarounds });
|
||||
powerVrShaderWorkarounds });
|
||||
mSpecializationConstants.push_back({
|
||||
+ReservedSpecializationConstants::CONFIG_STEREO_EYE_COUNT,
|
||||
(int)engine.getConfig().stereoscopicEyeCount });
|
||||
@@ -270,19 +278,18 @@ FMaterial::FMaterial(FEngine& engine, const Material::Builder& builder)
|
||||
false});
|
||||
}
|
||||
|
||||
for (const auto& [name, value] : builder->mConstantSpecializations) {
|
||||
auto found = std::find_if(
|
||||
constants.begin(), constants.end(), [name = name](const auto& constant) {
|
||||
return strncmp(constant.name.data(), name.data(), name.length()) == 0;
|
||||
});
|
||||
ASSERT_PRECONDITION(found != constants.end(),
|
||||
for (auto const& [name, value] : builder->mConstantSpecializations) {
|
||||
std::string_view const key{ name.data(), name.size() };
|
||||
auto pos = mSpecializationConstantsNameToIndex.find(key);
|
||||
ASSERT_PRECONDITION(pos != mSpecializationConstantsNameToIndex.end(),
|
||||
"The material %s does not have a constant parameter named %s.",
|
||||
mName.c_str_safe(), name.c_str());
|
||||
const char* const types[3] = {"an int", "a float", "a bool"};
|
||||
const char* const errorMessage =
|
||||
"The constant parameter %s on material %s is of type %s, but %s was "
|
||||
"provided.";
|
||||
switch (found->type) {
|
||||
auto& constant = mMaterialConstants[pos->second];
|
||||
switch (constant.type) {
|
||||
case ConstantType::INT:
|
||||
ASSERT_PRECONDITION(std::holds_alternative<int32_t>(value), errorMessage,
|
||||
name.c_str(), mName.c_str_safe(), "int", types[value.index()]);
|
||||
@@ -296,8 +303,7 @@ FMaterial::FMaterial(FEngine& engine, const Material::Builder& builder)
|
||||
name.c_str(), mName.c_str_safe(), "bool", types[value.index()]);
|
||||
break;
|
||||
}
|
||||
uint32_t const index =
|
||||
std::distance(constants.begin(), found) + CONFIG_MAX_RESERVED_SPEC_CONSTANTS;
|
||||
uint32_t const index = pos->second + CONFIG_MAX_RESERVED_SPEC_CONSTANTS;
|
||||
mSpecializationConstants.push_back({ index, value });
|
||||
}
|
||||
|
||||
@@ -462,16 +468,6 @@ FMaterial::~FMaterial() noexcept {
|
||||
}
|
||||
|
||||
void FMaterial::invalidate(Variant::type_t variantMask, Variant::type_t variantValue) noexcept {
|
||||
// update the spec constants that can change
|
||||
// TODO: should we just always update all of them?
|
||||
for (auto& item : mSpecializationConstants) {
|
||||
if (item.id == ReservedSpecializationConstants::CONFIG_DEBUG_DIRECTIONAL_SHADOWMAP) {
|
||||
item.value = mEngine.debug.shadowmap.debug_directional_shadowmap;
|
||||
} else if (item.id == ReservedSpecializationConstants::CONFIG_DEBUG_FROXEL_VISUALIZATION) {
|
||||
item.value = mEngine.debug.lighting.debug_froxel_visualization;
|
||||
}
|
||||
}
|
||||
|
||||
if (mMaterialDomain == MaterialDomain::SURFACE) {
|
||||
DriverApi& driverApi = mEngine.getDriverApi();
|
||||
auto& cachedPrograms = mCachedPrograms;
|
||||
@@ -841,4 +837,55 @@ void FMaterial::destroyPrograms(FEngine& engine) {
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<uint32_t> FMaterial::getSpecializationConstantId(std::string_view name) const noexcept {
|
||||
auto pos = mSpecializationConstantsNameToIndex.find(name);
|
||||
if (pos != mSpecializationConstantsNameToIndex.end()) {
|
||||
return pos->second + CONFIG_MAX_RESERVED_SPEC_CONSTANTS;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template<typename T, typename>
|
||||
bool FMaterial::setConstant(uint32_t id, T value) noexcept {
|
||||
size_t const maxId = mMaterialConstants.size() + CONFIG_MAX_RESERVED_SPEC_CONSTANTS;
|
||||
if (UTILS_LIKELY(id < maxId)) {
|
||||
if (id >= CONFIG_MAX_RESERVED_SPEC_CONSTANTS) {
|
||||
// Constant from the material itself (as opposed to the reserved ones)
|
||||
auto& constant = mMaterialConstants[id - CONFIG_MAX_RESERVED_SPEC_CONSTANTS];
|
||||
using ConstantType = backend::ConstantType;
|
||||
switch (constant.type) {
|
||||
case ConstantType::INT:
|
||||
if (!std::is_same_v<T, int32_t>) return false;
|
||||
break;
|
||||
case ConstantType::FLOAT:
|
||||
if (!std::is_same_v<T, float>) return false;
|
||||
break;
|
||||
case ConstantType::BOOL:
|
||||
if (!std::is_same_v<T, bool>) return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto pos = std::find_if(
|
||||
mSpecializationConstants.begin(), mSpecializationConstants.end(),
|
||||
[id](backend::Program::SpecializationConstant const& specializationConstant) {
|
||||
return specializationConstant.id == id;
|
||||
});
|
||||
if (pos != mSpecializationConstants.end()) {
|
||||
if (std::get<T>(pos->value) != value) {
|
||||
pos->value = value;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
mSpecializationConstants.push_back({ id, value });
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template bool FMaterial::setConstant<int32_t>(uint32_t id, int32_t value) noexcept;
|
||||
template bool FMaterial::setConstant<float>(uint32_t id, float value) noexcept;
|
||||
template bool FMaterial::setConstant<bool>(uint32_t id, bool value) noexcept;
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -165,6 +165,14 @@ public:
|
||||
|
||||
void destroyPrograms(FEngine& engine);
|
||||
|
||||
// return the id of a specialization constant specified by name for this material
|
||||
std::optional<uint32_t> getSpecializationConstantId(std::string_view name) const noexcept ;
|
||||
|
||||
// Sets a specialization constant by id. call is no-op if the id is invalid.
|
||||
// Return true is the value was changed.
|
||||
template<typename T, typename = Builder::is_supported_constant_parameter_t<T>>
|
||||
bool setConstant(uint32_t id, T value) noexcept;
|
||||
|
||||
#if FILAMENT_ENABLE_MATDBG
|
||||
void applyPendingEdits() noexcept;
|
||||
|
||||
@@ -261,6 +269,11 @@ private:
|
||||
|
||||
SamplerGroupBindingInfoList mSamplerGroupBindingInfoList;
|
||||
SamplerBindingToNameMap mSamplerBindingToNameMap;
|
||||
// Constants defined by this Material
|
||||
utils::FixedCapacityVector<MaterialConstant> mMaterialConstants;
|
||||
// A map from the Constant name to the mMaterialConstant index
|
||||
std::unordered_map<std::string_view, uint32_t> mSpecializationConstantsNameToIndex;
|
||||
// current specialization constants for the HwProgram
|
||||
utils::FixedCapacityVector<backend::Program::SpecializationConstant> mSpecializationConstants;
|
||||
|
||||
#if FILAMENT_ENABLE_MATDBG
|
||||
|
||||
@@ -491,6 +491,11 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
|
||||
hasDithering = false;
|
||||
hasFXAA = false;
|
||||
scale = 1.0f;
|
||||
} else {
|
||||
// This configures post-process materials by setting constant parameters
|
||||
if (taaOptions.enabled) {
|
||||
ppm.configureTemporalAntiAliasingMaterial(taaOptions);
|
||||
}
|
||||
}
|
||||
|
||||
const bool blendModeTranslucent = view.getBlendMode() == BlendMode::TRANSLUCENT;
|
||||
|
||||
@@ -28,6 +28,43 @@ material {
|
||||
name : filterWeights
|
||||
}
|
||||
],
|
||||
constants : [
|
||||
{
|
||||
type : bool,
|
||||
name : historyReprojection,
|
||||
default : true
|
||||
},
|
||||
{
|
||||
type : bool,
|
||||
name : filterHistory,
|
||||
default : true
|
||||
},
|
||||
{
|
||||
type : bool,
|
||||
name : filterInput,
|
||||
default : true
|
||||
},
|
||||
{
|
||||
type : int,
|
||||
name : boxClipping,
|
||||
default : 0
|
||||
},
|
||||
{
|
||||
type : int,
|
||||
name : boxType,
|
||||
default : 1
|
||||
},
|
||||
{
|
||||
type : bool,
|
||||
name : useYCoCg,
|
||||
default : false
|
||||
},
|
||||
{
|
||||
type : bool,
|
||||
name : preventFlickering,
|
||||
default : false
|
||||
}
|
||||
],
|
||||
variables : [
|
||||
vertex
|
||||
],
|
||||
@@ -73,34 +110,12 @@ fragment {
|
||||
// no clipping (for debugging only)
|
||||
#define BOX_CLIPPING_NONE 2
|
||||
|
||||
/* Configuration mobile/desktop */
|
||||
|
||||
#if FILAMENT_QUALITY < FILAMENT_QUALITY_HIGH
|
||||
#define BOX_CLIPPING BOX_CLIPPING_ACCURATE
|
||||
#define BOX_TYPE BOX_TYPE_VARIANCE
|
||||
#define USE_YCoCg 0
|
||||
#define FILTER_INPUT 1
|
||||
#define FILTER_HISTORY 0
|
||||
#else
|
||||
#define BOX_CLIPPING BOX_CLIPPING_ACCURATE
|
||||
#define BOX_TYPE BOX_TYPE_AABB_VARIANCE
|
||||
#define USE_YCoCg 1
|
||||
#define FILTER_INPUT 1
|
||||
#define FILTER_HISTORY 1
|
||||
#endif
|
||||
|
||||
/* debugging helper */
|
||||
|
||||
#define HISTORY_REPROJECTION 1
|
||||
#define PREVENT_FLICKERING 0 // FIXME: thin lines disapear
|
||||
|
||||
|
||||
float luma(const vec3 color) {
|
||||
#if USE_YCoCg
|
||||
return color.x;
|
||||
#else
|
||||
return luminance(color);
|
||||
#endif
|
||||
if (materialConstants_useYCoCg) {
|
||||
return color.x;
|
||||
} else {
|
||||
return luminance(color);
|
||||
}
|
||||
}
|
||||
|
||||
vec3 RGB_YCoCg(const vec3 c) {
|
||||
@@ -203,26 +218,27 @@ void postProcess(inout PostProcessInputs postProcess) {
|
||||
// read the depth buffer center sample for reprojection
|
||||
float depth = textureLod(materialParams_depth, uv.xy, 0.0).r;
|
||||
|
||||
#if HISTORY_REPROJECTION
|
||||
uv.zw = uvToRenderTargetUV(uv.zw);
|
||||
// reproject history to current frame
|
||||
highp vec4 q = materialParams.reprojection * vec4(uv.zw, depth, 1.0);
|
||||
uv.zw = (q.xy * (1.0 / q.w)) * 0.5 + 0.5;
|
||||
uv.zw = uvToRenderTargetUV(uv.zw);
|
||||
#endif
|
||||
if (materialConstants_historyReprojection) {
|
||||
uv.zw = uvToRenderTargetUV(uv.zw);
|
||||
// reproject history to current frame
|
||||
highp vec4 q = materialParams.reprojection * vec4(uv.zw, depth, 1.0);
|
||||
uv.zw = (q.xy * (1.0 / q.w)) * 0.5 + 0.5;
|
||||
uv.zw = uvToRenderTargetUV(uv.zw);
|
||||
}
|
||||
|
||||
// read center color and history samples
|
||||
vec4 color = textureLod(materialParams_color, uv.xy, 0.0);
|
||||
#if FILTER_HISTORY
|
||||
vec4 history = sampleTextureCatmullRom(materialParams_history, uv.zw,
|
||||
vec2(textureSize(materialParams_history, 0)));
|
||||
#else
|
||||
vec4 history = textureLod(materialParams_history, uv.zw, 0.0);
|
||||
#endif
|
||||
vec4 history;
|
||||
if (materialConstants_filterHistory) {
|
||||
history = sampleTextureCatmullRom(materialParams_history, uv.zw,
|
||||
vec2(textureSize(materialParams_history, 0)));
|
||||
} else {
|
||||
history = textureLod(materialParams_history, uv.zw, 0.0);
|
||||
}
|
||||
|
||||
#if USE_YCoCg
|
||||
history.rgb = RGB_YCoCg(history.rgb);
|
||||
#endif
|
||||
if (materialConstants_useYCoCg) {
|
||||
history.rgb = RGB_YCoCg(history.rgb);
|
||||
}
|
||||
|
||||
// build the history clamping box
|
||||
vec3 s[9];
|
||||
@@ -236,66 +252,72 @@ void postProcess(inout PostProcessInputs postProcess) {
|
||||
s[7] = textureLodOffset(materialParams_color, uv.xy, 0.0, ivec2( 0, TEXTURE_SPACE_UP)).rgb;
|
||||
s[8] = textureLodOffset(materialParams_color, uv.xy, 0.0, ivec2( 1, TEXTURE_SPACE_UP)).rgb;
|
||||
|
||||
#if USE_YCoCg
|
||||
for (int i = 0 ; i < 9 ; i++) {
|
||||
s[i] = RGB_YCoCg(s[i]);
|
||||
if (materialConstants_useYCoCg) {
|
||||
for (int i = 0; i < 9; i++) {
|
||||
s[i] = RGB_YCoCg(s[i]);
|
||||
}
|
||||
color.rgb = s[4].rgb;
|
||||
}
|
||||
color.rgb = s[4].rgb;
|
||||
#endif
|
||||
|
||||
#if FILTER_INPUT
|
||||
// unjitter/filter input
|
||||
vec4 filtered = vec4(0, 0, 0, color.a);
|
||||
for (int i = 0 ; i < 9 ; i++) {
|
||||
filtered.rgb += s[i] * materialParams.filterWeights[i];
|
||||
vec4 filtered;
|
||||
if (materialConstants_filterInput) {
|
||||
// unjitter/filter input
|
||||
filtered = vec4(0, 0, 0, color.a);
|
||||
for (int i = 0; i < 9; i++) {
|
||||
filtered.rgb += s[i] * materialParams.filterWeights[i];
|
||||
}
|
||||
} else {
|
||||
filtered = color;
|
||||
}
|
||||
#else
|
||||
vec4 filtered = color;
|
||||
#endif
|
||||
|
||||
#if BOX_TYPE == BOX_TYPE_AABB || BOX_TYPE == BOX_TYPE_AABB_VARIANCE
|
||||
vec3 boxmin = min(s[4], min(min(s[1], s[3]), min(s[5], s[7])));
|
||||
vec3 boxmax = max(s[4], max(max(s[1], s[3]), max(s[5], s[7])));
|
||||
vec3 box9min = min(boxmin, min(min(s[0], s[2]), min(s[6], s[8])));
|
||||
vec3 box9max = max(boxmax, max(max(s[0], s[2]), max(s[6], s[8])));
|
||||
// round the corners of the 3x3 box
|
||||
boxmin = (boxmin + box9min) * 0.5;
|
||||
boxmax = (boxmax + box9max) * 0.5;
|
||||
#endif
|
||||
|
||||
#if BOX_TYPE == BOX_TYPE_VARIANCE || BOX_TYPE == BOX_TYPE_AABB_VARIANCE
|
||||
// "An Excursion in Temporal Supersampling" by Marco Salvi
|
||||
vec3 m0 = s[4];
|
||||
vec3 m1 = s[4] * s[4];
|
||||
// we use only 5 samples instead of all 9
|
||||
for (int i = 1 ; i < 9 ; i+=2) {
|
||||
m0 += s[i];
|
||||
m1 += s[i] * s[i];
|
||||
vec3 boxmin;
|
||||
vec3 boxmax;
|
||||
if (materialConstants_boxType == BOX_TYPE_AABB ||
|
||||
materialConstants_boxType == BOX_TYPE_AABB_VARIANCE) {
|
||||
boxmin = min(s[4], min(min(s[1], s[3]), min(s[5], s[7])));
|
||||
boxmax = max(s[4], max(max(s[1], s[3]), max(s[5], s[7])));
|
||||
vec3 box9min = min(boxmin, min(min(s[0], s[2]), min(s[6], s[8])));
|
||||
vec3 box9max = max(boxmax, max(max(s[0], s[2]), max(s[6], s[8])));
|
||||
// round the corners of the 3x3 box
|
||||
boxmin = (boxmin + box9min) * 0.5;
|
||||
boxmax = (boxmax + box9max) * 0.5;
|
||||
}
|
||||
|
||||
if (materialConstants_boxType == BOX_TYPE_VARIANCE ||
|
||||
materialConstants_boxType == BOX_TYPE_AABB_VARIANCE) {
|
||||
// "An Excursion in Temporal Supersampling" by Marco Salvi
|
||||
vec3 m0 = s[4];
|
||||
vec3 m1 = s[4] * s[4];
|
||||
// we use only 5 samples instead of all 9
|
||||
for (int i = 1; i < 9; i+=2) {
|
||||
m0 += s[i];
|
||||
m1 += s[i] * s[i];
|
||||
}
|
||||
vec3 a0 = m0 * (1.0 / 5.0);
|
||||
vec3 a1 = m1 * (1.0 / 5.0);
|
||||
vec3 sigma = sqrt(a1 - a0 * a0);
|
||||
if (materialConstants_boxType == BOX_TYPE_VARIANCE) {
|
||||
boxmin = a0 - VARIANCE_GAMMA * sigma;
|
||||
boxmax = a0 + VARIANCE_GAMMA * sigma;
|
||||
} else {
|
||||
boxmin = min(boxmin, a0 - VARIANCE_GAMMA * sigma);
|
||||
boxmax = max(boxmax, a0 + VARIANCE_GAMMA * sigma);
|
||||
}
|
||||
}
|
||||
vec3 a0 = m0 * (1.0 / 5.0);
|
||||
vec3 a1 = m1 * (1.0 / 5.0);
|
||||
vec3 sigma = sqrt(a1 - a0 * a0);
|
||||
#if BOX_TYPE == BOX_TYPE_VARIANCE
|
||||
vec3 boxmin = a0 - VARIANCE_GAMMA * sigma;
|
||||
vec3 boxmax = a0 + VARIANCE_GAMMA * sigma;
|
||||
#else
|
||||
boxmin = min(boxmin, a0 - VARIANCE_GAMMA * sigma);
|
||||
boxmax = max(boxmax, a0 + VARIANCE_GAMMA * sigma);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// history clamping
|
||||
history = clipToBox(BOX_CLIPPING, boxmin, boxmax, filtered, history);
|
||||
history = clipToBox(materialConstants_boxClipping, boxmin, boxmax, filtered, history);
|
||||
|
||||
float lumaColor = luma(filtered.rgb);
|
||||
float lumaHistory = luma(history.rgb);
|
||||
|
||||
float alpha = materialParams.alpha;
|
||||
#if PREVENT_FLICKERING
|
||||
// [Lottes] prevents flickering by modulating the blend weight by the difference in luma
|
||||
float diff = 1.0 - abs(lumaColor - lumaHistory) / (0.001 + max(lumaColor, lumaHistory));
|
||||
alpha *= diff * diff;
|
||||
#endif
|
||||
if (materialConstants_preventFlickering) {
|
||||
// [Lottes] prevents flickering by modulating the blend weight by the difference in luma
|
||||
float diff = 1.0 - abs(lumaColor - lumaHistory) / (0.001 + max(lumaColor, lumaHistory));
|
||||
alpha *= diff * diff;
|
||||
}
|
||||
|
||||
// tonemapping for handling HDR
|
||||
filtered.rgb *= 1.0 / (1.0 + lumaColor);
|
||||
@@ -307,9 +329,9 @@ void postProcess(inout PostProcessInputs postProcess) {
|
||||
// untonemap result
|
||||
result.rgb *= 1.0 / (1.0 - luma(result.rgb));
|
||||
|
||||
#if USE_YCoCg
|
||||
result.rgb = YCoCg_RGB(result.rgb);
|
||||
#endif
|
||||
if (materialConstants_useYCoCg) {
|
||||
result.rgb = YCoCg_RGB(result.rgb);
|
||||
}
|
||||
|
||||
// store result (which will becomes new history)
|
||||
// we could end-up with negative values due to the bicubic filter, which never recover on
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
|
||||
namespace filament {
|
||||
|
||||
static constexpr size_t POST_PROCESS_VARIANT_COUNT = 2;
|
||||
static constexpr size_t POST_PROCESS_VARIANT_BITS = 1;
|
||||
static constexpr size_t POST_PROCESS_VARIANT_COUNT = (1u << POST_PROCESS_VARIANT_BITS);
|
||||
static constexpr size_t POST_PROCESS_VARIANT_MASK = POST_PROCESS_VARIANT_COUNT - 1;
|
||||
enum class PostProcessVariant : uint8_t {
|
||||
OPAQUE,
|
||||
TRANSLUCENT
|
||||
@@ -135,11 +137,15 @@ template<>
|
||||
struct utils::EnableIntegerOperators<filament::SamplerBindingPoints> : public std::true_type {};
|
||||
template<>
|
||||
struct utils::EnableIntegerOperators<filament::ReservedSpecializationConstants> : public std::true_type {};
|
||||
template<>
|
||||
struct utils::EnableIntegerOperators<filament::PostProcessVariant> : public std::true_type {};
|
||||
|
||||
template<>
|
||||
inline constexpr size_t utils::Enum::count<filament::UniformBindingPoints>() { return 9; }
|
||||
template<>
|
||||
inline constexpr size_t utils::Enum::count<filament::SamplerBindingPoints>() { return 4; }
|
||||
template<>
|
||||
inline constexpr size_t utils::Enum::count<filament::PostProcessVariant>() { return filament::POST_PROCESS_VARIANT_COUNT; }
|
||||
|
||||
static_assert(utils::Enum::count<filament::UniformBindingPoints>() <= filament::backend::CONFIG_UNIFORM_BINDING_COUNT);
|
||||
static_assert(utils::Enum::count<filament::SamplerBindingPoints>() <= filament::backend::CONFIG_SAMPLER_BINDING_COUNT);
|
||||
|
||||
@@ -35,7 +35,7 @@ struct hashCStrings {
|
||||
typedef size_t result_type;
|
||||
result_type operator()(argument_type cstr) const noexcept {
|
||||
size_t hash = 5381;
|
||||
while (int c = *cstr++) {
|
||||
while (int const c = *cstr++) {
|
||||
hash = (hash * 33u) ^ size_t(c);
|
||||
}
|
||||
return hash;
|
||||
|
||||
@@ -647,6 +647,44 @@ std::ostream& operator<<(std::ostream& out, const MultiSampleAntiAliasingOptions
|
||||
<< "}";
|
||||
}
|
||||
|
||||
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, TemporalAntiAliasingOptions::BoxType* out) {
|
||||
if (0 == compare(tokens[i], jsonChunk, "AABB")) { *out = TemporalAntiAliasingOptions::BoxType::AABB; }
|
||||
else if (0 == compare(tokens[i], jsonChunk, "VARIANCE")) { *out = TemporalAntiAliasingOptions::BoxType::VARIANCE; }
|
||||
else if (0 == compare(tokens[i], jsonChunk, "AABB_VARIANCE")) { *out = TemporalAntiAliasingOptions::BoxType::AABB_VARIANCE; }
|
||||
else {
|
||||
slog.w << "Invalid TemporalAntiAliasingOptions::BoxType: '" << STR(tokens[i], jsonChunk) << "'" << io::endl;
|
||||
}
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, TemporalAntiAliasingOptions::BoxType in) {
|
||||
switch (in) {
|
||||
case TemporalAntiAliasingOptions::BoxType::AABB: return out << "\"AABB\"";
|
||||
case TemporalAntiAliasingOptions::BoxType::VARIANCE: return out << "\"VARIANCE\"";
|
||||
case TemporalAntiAliasingOptions::BoxType::AABB_VARIANCE: return out << "\"AABB_VARIANCE\"";
|
||||
}
|
||||
return out << "\"INVALID\"";
|
||||
}
|
||||
|
||||
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, TemporalAntiAliasingOptions::BoxClipping* out) {
|
||||
if (0 == compare(tokens[i], jsonChunk, "ACCURATE")) { *out = TemporalAntiAliasingOptions::BoxClipping::ACCURATE; }
|
||||
else if (0 == compare(tokens[i], jsonChunk, "CLAMP")) { *out = TemporalAntiAliasingOptions::BoxClipping::CLAMP; }
|
||||
else if (0 == compare(tokens[i], jsonChunk, "NONE")) { *out = TemporalAntiAliasingOptions::BoxClipping::NONE; }
|
||||
else {
|
||||
slog.w << "Invalid TemporalAntiAliasingOptions::BoxClipping: '" << STR(tokens[i], jsonChunk) << "'" << io::endl;
|
||||
}
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, TemporalAntiAliasingOptions::BoxClipping in) {
|
||||
switch (in) {
|
||||
case TemporalAntiAliasingOptions::BoxClipping::ACCURATE: return out << "\"ACCURATE\"";
|
||||
case TemporalAntiAliasingOptions::BoxClipping::CLAMP: return out << "\"CLAMP\"";
|
||||
case TemporalAntiAliasingOptions::BoxClipping::NONE: return out << "\"NONE\"";
|
||||
}
|
||||
return out << "\"INVALID\"";
|
||||
}
|
||||
|
||||
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, TemporalAntiAliasingOptions* out) {
|
||||
CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
int size = tokens[i++].size;
|
||||
@@ -659,6 +697,20 @@ int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, TemporalAntiAli
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->feedback);
|
||||
} else if (compare(tok, jsonChunk, "enabled") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->enabled);
|
||||
} else if (compare(tok, jsonChunk, "filterHistory") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->filterHistory);
|
||||
} else if (compare(tok, jsonChunk, "filterInput") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->filterInput);
|
||||
} else if (compare(tok, jsonChunk, "useYCoCg") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->useYCoCg);
|
||||
} else if (compare(tok, jsonChunk, "boxType") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->boxType);
|
||||
} else if (compare(tok, jsonChunk, "boxClipping") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->boxClipping);
|
||||
} else if (compare(tok, jsonChunk, "preventFlickering") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->preventFlickering);
|
||||
} else if (compare(tok, jsonChunk, "historyReprojection") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->historyReprojection);
|
||||
} else {
|
||||
slog.w << "Invalid TemporalAntiAliasingOptions key: '" << STR(tok, jsonChunk) << "'" << io::endl;
|
||||
i = parse(tokens, i + 1);
|
||||
@@ -675,7 +727,14 @@ std::ostream& operator<<(std::ostream& out, const TemporalAntiAliasingOptions& i
|
||||
return out << "{\n"
|
||||
<< "\"filterWidth\": " << (in.filterWidth) << ",\n"
|
||||
<< "\"feedback\": " << (in.feedback) << ",\n"
|
||||
<< "\"enabled\": " << to_string(in.enabled) << "\n"
|
||||
<< "\"enabled\": " << to_string(in.enabled) << ",\n"
|
||||
<< "\"filterHistory\": " << to_string(in.filterHistory) << ",\n"
|
||||
<< "\"filterInput\": " << to_string(in.filterInput) << ",\n"
|
||||
<< "\"useYCoCg\": " << to_string(in.useYCoCg) << ",\n"
|
||||
<< "\"boxType\": " << (in.boxType) << ",\n"
|
||||
<< "\"boxClipping\": " << (in.boxClipping) << ",\n"
|
||||
<< "\"preventFlickering\": " << to_string(in.preventFlickering) << ",\n"
|
||||
<< "\"historyReprojection\": " << to_string(in.historyReprojection) << "\n"
|
||||
<< "}";
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,12 @@ std::ostream& operator<<(std::ostream& out, const AmbientOcclusionOptions& in);
|
||||
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, MultiSampleAntiAliasingOptions* out);
|
||||
std::ostream& operator<<(std::ostream& out, const MultiSampleAntiAliasingOptions& in);
|
||||
|
||||
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, TemporalAntiAliasingOptions::BoxType* out);
|
||||
std::ostream& operator<<(std::ostream& out, TemporalAntiAliasingOptions::BoxType in);
|
||||
|
||||
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, TemporalAntiAliasingOptions::BoxClipping* out);
|
||||
std::ostream& operator<<(std::ostream& out, TemporalAntiAliasingOptions::BoxClipping in);
|
||||
|
||||
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, TemporalAntiAliasingOptions* out);
|
||||
std::ostream& operator<<(std::ostream& out, const TemporalAntiAliasingOptions& in);
|
||||
|
||||
|
||||
@@ -792,6 +792,22 @@ void ViewerGui::updateUserInterface() {
|
||||
ImGui::Checkbox("Lens Flare", &mSettings.view.bloom.lensFlare);
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("TAA Options")) {
|
||||
ImGui::Checkbox("History Reprojection", &mSettings.view.taa.historyReprojection);
|
||||
ImGui::SliderFloat("Feedback", &mSettings.view.taa.feedback, 0.0f, 1.0f);
|
||||
ImGui::Checkbox("Filter History", &mSettings.view.taa.filterHistory);
|
||||
ImGui::Checkbox("Filter Input", &mSettings.view.taa.filterInput);
|
||||
ImGui::SliderFloat("FilterWidth", &mSettings.view.taa.filterWidth, 0.0f, 1.0f);
|
||||
ImGui::Checkbox("Use YCoCg", &mSettings.view.taa.useYCoCg);
|
||||
ImGui::Checkbox("Prevent Flickering", &mSettings.view.taa.preventFlickering);
|
||||
int boxClipping = (int)mSettings.view.taa.boxClipping;
|
||||
int boxType = (int)mSettings.view.taa.boxType;
|
||||
ImGui::Combo("Box Clipping", &boxClipping, "Accurate\0Clamp\0None\0\0");
|
||||
ImGui::Combo("Box Type", &boxType, "AABB\0Variance\0Both\0\0");
|
||||
mSettings.view.taa.boxClipping = (TemporalAntiAliasingOptions::BoxClipping)boxClipping;
|
||||
mSettings.view.taa.boxType = (TemporalAntiAliasingOptions::BoxType)boxType;
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("SSAO Options")) {
|
||||
auto& ssao = mSettings.view.ssao;
|
||||
|
||||
|
||||
@@ -140,6 +140,13 @@ Filament.loadGeneratedExtensions = function() {
|
||||
filterWidth: 1.0,
|
||||
feedback: 0.04,
|
||||
enabled: false,
|
||||
filterHistory: true,
|
||||
filterInput: true,
|
||||
useYCoCg: false,
|
||||
boxType: Filament.View$TemporalAntiAliasingOptions$BoxType.VARIANCE,
|
||||
boxClipping: Filament.View$TemporalAntiAliasingOptions$BoxClipping.ACCURATE,
|
||||
preventFlickering: false,
|
||||
historyReprojection: true,
|
||||
};
|
||||
return Object.assign(options, overrides);
|
||||
};
|
||||
|
||||
Vendored
+44
-1
@@ -1636,13 +1636,28 @@ export interface View$MultiSampleAntiAliasingOptions {
|
||||
customResolve?: boolean;
|
||||
}
|
||||
|
||||
export enum View$TemporalAntiAliasingOptions$BoxType {
|
||||
AABB, // use an AABB neighborhood
|
||||
VARIANCE, // use the variance of the neighborhood
|
||||
AABB_VARIANCE, // use both AABB and variance
|
||||
}
|
||||
|
||||
export enum View$TemporalAntiAliasingOptions$BoxClipping {
|
||||
ACCURATE, // Accurate box clipping
|
||||
CLAMP, // clamping
|
||||
NONE, // no rejections (use for debugging)
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for Temporal Anti-aliasing (TAA)
|
||||
* Most TAA parameters are extremely costly to change, as they will trigger the TAA post-process
|
||||
* shaders to be recompiled. These options should be changed or set during initialization.
|
||||
* `filterWidth` and `feedback`, however, could be changed an any time.
|
||||
* @see setTemporalAntiAliasingOptions()
|
||||
*/
|
||||
export interface View$TemporalAntiAliasingOptions {
|
||||
/**
|
||||
* reconstruction filter width typically between 0 (sharper, aliased) and 1 (smoother)
|
||||
* reconstruction filter width typically between 0.2 (sharper, aliased) and 1 (smoother)
|
||||
*/
|
||||
filterWidth?: number;
|
||||
/**
|
||||
@@ -1653,6 +1668,34 @@ export interface View$TemporalAntiAliasingOptions {
|
||||
* enables or disables temporal anti-aliasing
|
||||
*/
|
||||
enabled?: boolean;
|
||||
/**
|
||||
* whether to filter the history buffer
|
||||
*/
|
||||
filterHistory?: boolean;
|
||||
/**
|
||||
* whether to apply the reconstruction filter to the input
|
||||
*/
|
||||
filterInput?: boolean;
|
||||
/**
|
||||
* whether to use the YcoCg color-space for history rejection
|
||||
*/
|
||||
useYCoCg?: boolean;
|
||||
/**
|
||||
* type of color gamut box
|
||||
*/
|
||||
boxType?: View$TemporalAntiAliasingOptions$BoxType;
|
||||
/**
|
||||
* clipping algorithm
|
||||
*/
|
||||
boxClipping?: View$TemporalAntiAliasingOptions$BoxClipping;
|
||||
/**
|
||||
* adjust the feedback dynamically to reduce flickering
|
||||
*/
|
||||
preventFlickering?: boolean;
|
||||
/**
|
||||
* whether to apply history reprojection (debug option)
|
||||
*/
|
||||
historyReprojection?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -120,6 +120,13 @@ value_object<View::TemporalAntiAliasingOptions>("View$TemporalAntiAliasingOption
|
||||
.field("filterWidth", &View::TemporalAntiAliasingOptions::filterWidth)
|
||||
.field("feedback", &View::TemporalAntiAliasingOptions::feedback)
|
||||
.field("enabled", &View::TemporalAntiAliasingOptions::enabled)
|
||||
.field("filterHistory", &View::TemporalAntiAliasingOptions::filterHistory)
|
||||
.field("filterInput", &View::TemporalAntiAliasingOptions::filterInput)
|
||||
.field("useYCoCg", &View::TemporalAntiAliasingOptions::useYCoCg)
|
||||
.field("boxType", &View::TemporalAntiAliasingOptions::boxType)
|
||||
.field("boxClipping", &View::TemporalAntiAliasingOptions::boxClipping)
|
||||
.field("preventFlickering", &View::TemporalAntiAliasingOptions::preventFlickering)
|
||||
.field("historyReprojection", &View::TemporalAntiAliasingOptions::historyReprojection)
|
||||
;
|
||||
|
||||
value_object<View::ScreenSpaceReflectionsOptions>("View$ScreenSpaceReflectionsOptions")
|
||||
|
||||
@@ -33,6 +33,18 @@ enum_<View::DepthOfFieldOptions::Filter>("View$DepthOfFieldOptions$Filter")
|
||||
.value("MEDIAN", View::DepthOfFieldOptions::Filter::MEDIAN)
|
||||
;
|
||||
|
||||
enum_<View::TemporalAntiAliasingOptions::BoxType>("View$TemporalAntiAliasingOptions$BoxType")
|
||||
.value("AABB", View::TemporalAntiAliasingOptions::BoxType::AABB)
|
||||
.value("VARIANCE", View::TemporalAntiAliasingOptions::BoxType::VARIANCE)
|
||||
.value("AABB_VARIANCE", View::TemporalAntiAliasingOptions::BoxType::AABB_VARIANCE)
|
||||
;
|
||||
|
||||
enum_<View::TemporalAntiAliasingOptions::BoxClipping>("View$TemporalAntiAliasingOptions$BoxClipping")
|
||||
.value("ACCURATE", View::TemporalAntiAliasingOptions::BoxClipping::ACCURATE)
|
||||
.value("CLAMP", View::TemporalAntiAliasingOptions::BoxClipping::CLAMP)
|
||||
.value("NONE", View::TemporalAntiAliasingOptions::BoxClipping::NONE)
|
||||
;
|
||||
|
||||
enum_<View::AntiAliasing>("View$AntiAliasing")
|
||||
.value("NONE", View::AntiAliasing::NONE)
|
||||
.value("FXAA", View::AntiAliasing::FXAA)
|
||||
|
||||
Reference in New Issue
Block a user