Compare commits
14 Commits
v1.49.3
...
exv/webgl-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea9fdbeb5c | ||
|
|
5fd7a4e153 | ||
|
|
20ff230b92 | ||
|
|
44ff79ad34 | ||
|
|
102d2db008 | ||
|
|
5c9039e650 | ||
|
|
1203c24f06 | ||
|
|
9704d27aeb | ||
|
|
c6f2c3fc1c | ||
|
|
2faf868341 | ||
|
|
81f6260843 | ||
|
|
1a9063d53a | ||
|
|
6062b3c8c6 | ||
|
|
d9186c44ba |
@@ -7,3 +7,5 @@ for next branch cut* header.
|
||||
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
|
||||
|
||||
## Release notes for next branch cut
|
||||
|
||||
- Metal: fix some shader artifacts by disabling fast math optimizations.
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.49.2'
|
||||
implementation 'com.google.android.filament:filament-android:1.49.3'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
|
||||
iOS projects can use CocoaPods to install the latest release:
|
||||
|
||||
```shell
|
||||
pod 'Filament', '~> 1.49.2'
|
||||
pod 'Filament', '~> 1.49.3'
|
||||
```
|
||||
|
||||
### Snapshots
|
||||
|
||||
@@ -7,8 +7,12 @@ A new header is inserted each time a *tag* is created.
|
||||
Instead, if you are authoring a PR for the main branch, add your release note to
|
||||
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
|
||||
|
||||
## v1.50.0
|
||||
- engine: TAA now supports 4x upscaling [BETA] [⚠️ **New Material Version**]
|
||||
|
||||
## v1.49.3
|
||||
|
||||
- matc: Generate stereo variants for FL0 materials [⚠️ **Recompile materials**]
|
||||
|
||||
## v1.49.2
|
||||
|
||||
|
||||
@@ -1637,6 +1637,10 @@ public class View {
|
||||
* circle of confusion scale factor (amount of blur)
|
||||
*/
|
||||
public float cocScale = 1.0f;
|
||||
/**
|
||||
* width/height aspect ratio of the circle of confusion (simulate anamorphic lenses)
|
||||
*/
|
||||
public float cocAspectRatio = 1.0f;
|
||||
/**
|
||||
* maximum aperture diameter in meters (zero to disable rotation)
|
||||
*/
|
||||
@@ -1878,7 +1882,7 @@ 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`, `feedback` and `jitterPattern`, however, can be changed at any time.
|
||||
* `filterWidth`, `feedback` and `jitterPattern`, however, could be changed at any time.
|
||||
*
|
||||
* `feedback` of 0.1 effectively accumulates a maximum of 19 samples in steady state.
|
||||
* see "A Survey of Temporal Antialiasing Techniques" by Lei Yang and all for more information.
|
||||
@@ -1931,10 +1935,18 @@ public class View {
|
||||
* history feedback, between 0 (maximum temporal AA) and 1 (no temporal AA).
|
||||
*/
|
||||
public float feedback = 0.12f;
|
||||
/**
|
||||
* texturing lod bias (typically -1 or -2)
|
||||
*/
|
||||
public float lodBias = -1.0f;
|
||||
/**
|
||||
* enables or disables temporal anti-aliasing
|
||||
*/
|
||||
public boolean enabled = false;
|
||||
/**
|
||||
* 4x TAA upscaling. Disables Dynamic Resolution. [BETA]
|
||||
*/
|
||||
public boolean upscaling = false;
|
||||
/**
|
||||
* whether to filter the history buffer
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.49.2
|
||||
VERSION_NAME=1.49.3
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -103,10 +103,19 @@ void MetalShaderCompiler::terminate() noexcept {
|
||||
NSString* objcSource = [[NSString alloc] initWithBytes:source.data()
|
||||
length:source.size() - 1
|
||||
encoding:NSUTF8StringEncoding];
|
||||
|
||||
// By default, Metal uses the most recent language version.
|
||||
MTLCompileOptions* options = [MTLCompileOptions new];
|
||||
|
||||
// Disable Fast Math optimizations.
|
||||
// This ensures that operations adhere to IEEE standards for floating-point arithmetic,
|
||||
// which is crucial for half precision floats in scenarios where fast math optimizations
|
||||
// lead to inaccuracies, such as in handling special values like NaN or Infinity.
|
||||
options.fastMathEnabled = NO;
|
||||
|
||||
NSError* error = nil;
|
||||
// When options is nil, Metal uses the most recent language version available.
|
||||
id<MTLLibrary> library = [device newLibraryWithSource:objcSource
|
||||
options:nil
|
||||
options:options
|
||||
error:&error];
|
||||
if (library == nil) {
|
||||
if (error) {
|
||||
|
||||
@@ -293,6 +293,7 @@ struct DepthOfFieldOptions {
|
||||
MEDIAN
|
||||
};
|
||||
float cocScale = 1.0f; //!< circle of confusion scale factor (amount of blur)
|
||||
float cocAspectRatio = 1.0f; //!< width/height aspect ratio of the circle of confusion (simulate anamorphic lenses)
|
||||
float maxApertureDiameter = 0.01f; //!< maximum aperture diameter in meters (zero to disable rotation)
|
||||
bool enabled = false; //!< enable or disable depth of field effect
|
||||
Filter filter = Filter::MEDIAN; //!< filter to use for filling gaps in the kernel
|
||||
@@ -426,7 +427,7 @@ 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`, `feedback` and `jitterPattern`, however, could be changed an any time.
|
||||
* `filterWidth`, `feedback` and `jitterPattern`, however, can be changed at any time.
|
||||
*
|
||||
* `feedback` of 0.1 effectively accumulates a maximum of 19 samples in steady state.
|
||||
* see "A Survey of Temporal Antialiasing Techniques" by Lei Yang and all for more information.
|
||||
@@ -436,7 +437,9 @@ struct MultiSampleAntiAliasingOptions {
|
||||
struct TemporalAntiAliasingOptions {
|
||||
float filterWidth = 1.0f; //!< reconstruction filter width typically between 0.2 (sharper, aliased) and 1.5 (smoother)
|
||||
float feedback = 0.12f; //!< history feedback, between 0 (maximum temporal AA) and 1 (no temporal AA).
|
||||
float lodBias = -1.0f; //!< texturing lod bias (typically -1 or -2)
|
||||
bool enabled = false; //!< enables or disables temporal anti-aliasing
|
||||
bool upscaling = false; //!< 4x TAA upscaling. Disables Dynamic Resolution. [BETA]
|
||||
|
||||
enum class BoxType : uint8_t {
|
||||
AABB, //!< use an AABB neighborhood
|
||||
|
||||
@@ -71,8 +71,7 @@ void PerShadowMapUniforms::prepareCamera(Transaction const& transaction,
|
||||
s.clipControl = engine.getDriverApi().getClipSpaceParams();
|
||||
}
|
||||
|
||||
void PerShadowMapUniforms::prepareLodBias(Transaction const& transaction,
|
||||
float bias) noexcept {
|
||||
void PerShadowMapUniforms::prepareLodBias(Transaction const& transaction, float bias) noexcept {
|
||||
auto& s = edit(transaction);
|
||||
s.lodBias = bias;
|
||||
}
|
||||
|
||||
@@ -96,9 +96,10 @@ void PerViewUniforms::prepareCamera(FEngine& engine, const CameraInfo& camera) n
|
||||
s.clipControl = engine.getDriverApi().getClipSpaceParams();
|
||||
}
|
||||
|
||||
void PerViewUniforms::prepareLodBias(float bias) noexcept {
|
||||
void PerViewUniforms::prepareLodBias(float bias, float2 derivativesScale) noexcept {
|
||||
auto& s = mUniforms.edit();
|
||||
s.lodBias = bias;
|
||||
s.derivativesScale = derivativesScale;
|
||||
}
|
||||
|
||||
void PerViewUniforms::prepareExposure(float ev100) noexcept {
|
||||
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
void terminate(backend::DriverApi& driver);
|
||||
|
||||
void prepareCamera(FEngine& engine, const CameraInfo& camera) noexcept;
|
||||
void prepareLodBias(float bias) noexcept;
|
||||
void prepareLodBias(float bias, math::float2 derivativesScale) noexcept;
|
||||
|
||||
/*
|
||||
* @param viewport viewport (should be same as RenderPassParams::viewport)
|
||||
|
||||
@@ -27,9 +27,12 @@
|
||||
#include "details/Engine.h"
|
||||
|
||||
#include "fg/FrameGraph.h"
|
||||
#include "fg/FrameGraphId.h"
|
||||
#include "fg/FrameGraphResources.h"
|
||||
#include "fg/FrameGraphTexture.h"
|
||||
|
||||
#include "fsr.h"
|
||||
#include "FrameHistory.h"
|
||||
#include "PerViewUniforms.h"
|
||||
#include "RenderPass.h"
|
||||
|
||||
@@ -41,15 +44,44 @@
|
||||
|
||||
#include "generated/resources/materials.h"
|
||||
|
||||
#include <filament/Material.h>
|
||||
#include <filament/MaterialEnums.h>
|
||||
#include <filament/Options.h>
|
||||
#include <filament/Viewport.h>
|
||||
|
||||
#include <private/filament/EngineEnums.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/DriverApiForward.h>
|
||||
#include <backend/Handle.h>
|
||||
#include <backend/PipelineState.h>
|
||||
#include <backend/PixelBufferDescriptor.h>
|
||||
|
||||
#include <private/backend/BackendUtils.h>
|
||||
|
||||
#include <math/half.h>
|
||||
#include <math/mat2.h>
|
||||
#include <math/mat3.h>
|
||||
#include <math/mat4.h>
|
||||
#include <math/scalar.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/BitmaskEnum.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <string_view>
|
||||
#include <variant>
|
||||
#include <utility>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
@@ -772,7 +804,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::screenSpaceAmbientOcclusion(
|
||||
auto ssao = resources.getRenderPassInfo();
|
||||
auto const& desc = resources.getDescriptor(data.depth);
|
||||
|
||||
// estimate of the size in pixel of a 1m tall/wide object viewed from 1m away (i.e. at z=-1)
|
||||
// Estimate of the size in pixel units of a 1m tall/wide object viewed from 1m away (i.e. at z=-1)
|
||||
const float projectionScale = std::min(
|
||||
0.5f * cameraInfo.projection[0].x * desc.width,
|
||||
0.5f * cameraInfo.projection[1].y * desc.height);
|
||||
@@ -929,7 +961,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::bilateralBlurPass(FrameGraph
|
||||
auto const& desc = resources.getDescriptor(data.blurred);
|
||||
|
||||
// unnormalized gaussian half-kernel of a given standard deviation
|
||||
// returns number of samples stored in array (max 16)
|
||||
// returns number of samples stored in the array (max 16)
|
||||
constexpr size_t kernelArraySize = 16; // limited by bilateralBlur.mat
|
||||
auto gaussianKernel =
|
||||
[kernelArraySize](float* outKernel, size_t gaussianWidth, float stdDev) -> uint32_t {
|
||||
@@ -973,7 +1005,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::generateGaussianMipmap(Frame
|
||||
|
||||
auto const subResourceDesc = fg.getSubResourceDescriptor(input);
|
||||
|
||||
// create one subresource per level to be generated from the input. These will be our
|
||||
// Create one subresource per level to be generated from the input. These will be our
|
||||
// destinations.
|
||||
struct MipmapPassData {
|
||||
FixedCapacityVector<FrameGraphId<FrameGraphTexture>> out;
|
||||
@@ -1134,7 +1166,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::gaussianBlurPass(FrameGraph&
|
||||
size_t const m = computeGaussianCoefficients(kernel,
|
||||
std::min(sizeof(kernel) / sizeof(*kernel), kernelStorageSize));
|
||||
|
||||
std::string_view sourceParameterName = is2dArray ? "sourceArray"sv : "source"sv;
|
||||
std::string_view const sourceParameterName = is2dArray ? "sourceArray"sv : "source"sv;
|
||||
// horizontal pass
|
||||
mi->setParameter(sourceParameterName, hwIn, {
|
||||
.filterMag = SamplerMagFilter::LINEAR,
|
||||
@@ -1180,7 +1212,7 @@ PostProcessManager::ScreenSpaceRefConfig PostProcessManager::prepareMipmapSSR(Fr
|
||||
|
||||
// The kernel-size was determined empirically so that we don't get too many artifacts
|
||||
// due to the down-sampling with a box filter (which happens implicitly).
|
||||
// requires only 6 stored coefficients and 11 tap/pass
|
||||
// Requires only 6 stored coefficients and 11 tap/pass
|
||||
// e.g.: size of 13 (4 stored coefficients)
|
||||
// +-------+-------+-------*===*-------+-------+-------+
|
||||
// ... | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | ...
|
||||
@@ -1344,10 +1376,10 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::generateMipmapSSR(
|
||||
FrameGraphId<FrameGraphTexture> output,
|
||||
bool needInputDuplication, ScreenSpaceRefConfig const& config) noexcept {
|
||||
|
||||
// descriptor of our actual input image (e.g. reflection buffer or refraction framebuffer)
|
||||
// Descriptor of our actual input image (e.g. reflection buffer or refraction framebuffer)
|
||||
auto const& desc = fg.getDescriptor(input);
|
||||
|
||||
// descriptor of the destination. output is a subresource (i.e. a layer of a 2D array)
|
||||
// Descriptor of the destination. `output` is a subresource (i.e. a layer of a 2D array)
|
||||
auto const& outDesc = fg.getDescriptor(output);
|
||||
|
||||
/*
|
||||
@@ -1396,7 +1428,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> depth,
|
||||
const CameraInfo& cameraInfo,
|
||||
bool translucent,
|
||||
float bokehAspectRatio,
|
||||
float2 bokehScale,
|
||||
const DepthOfFieldOptions& dofOptions) noexcept {
|
||||
|
||||
assert_invariant(depth);
|
||||
@@ -1407,7 +1439,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
|
||||
const TextureFormat format = translucent ? TextureFormat::RGBA16F
|
||||
: TextureFormat::R11F_G11F_B10F;
|
||||
|
||||
// rotate the bokeh based on the aperture diameter (i.e. angle of the blades)
|
||||
// Rotate the bokeh based on the aperture diameter (i.e. angle of the blades)
|
||||
float bokehAngle = f::PI / 6.0f;
|
||||
if (dofOptions.maxApertureDiameter > 0.0f) {
|
||||
bokehAngle += f::PI_2 * saturate(cameraInfo.A / dofOptions.maxApertureDiameter);
|
||||
@@ -1786,8 +1818,8 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
|
||||
mi->setParameter("tiles", tilesCocMinMax,
|
||||
{ .filterMin = SamplerMinFilter::NEAREST });
|
||||
mi->setParameter("cocToTexelScale", float2{
|
||||
bokehAspectRatio / (inputDesc.width * dofResolution),
|
||||
1.0 / (inputDesc.height * dofResolution)
|
||||
bokehScale.x / (inputDesc.width * dofResolution),
|
||||
bokehScale.y / (inputDesc.height * dofResolution)
|
||||
});
|
||||
mi->setParameter("cocToPixelScale", (1.0f / float(dofResolution)));
|
||||
mi->setParameter("ringCounts", float4{
|
||||
@@ -1893,14 +1925,6 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
|
||||
return ppDoFCombine->output;
|
||||
}
|
||||
|
||||
PostProcessManager::BloomPassOutput PostProcessManager::bloom(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> input,
|
||||
BloomOptions& inoutBloomOptions,
|
||||
backend::TextureFormat outFormat,
|
||||
math::float2 scale) noexcept {
|
||||
return bloomPass(fg, input, outFormat, inoutBloomOptions, scale);
|
||||
}
|
||||
|
||||
FrameGraphId<FrameGraphTexture> PostProcessManager::downscalePass(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> input,
|
||||
FrameGraphTexture::Descriptor const& outDesc,
|
||||
@@ -1932,9 +1956,11 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::downscalePass(FrameGraph& fg
|
||||
return downsamplePass->output;
|
||||
}
|
||||
|
||||
PostProcessManager::BloomPassOutput PostProcessManager::bloomPass(FrameGraph& fg,
|
||||
PostProcessManager::BloomPassOutput PostProcessManager::bloom(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> input, TextureFormat outFormat,
|
||||
BloomOptions& inoutBloomOptions, float2 scale) noexcept {
|
||||
BloomOptions& inoutBloomOptions,
|
||||
TemporalAntiAliasingOptions const& taaOptions,
|
||||
float2 scale) noexcept {
|
||||
|
||||
// Figure out a good size for the bloom buffer. We must use a fixed bloom buffer size so
|
||||
// that the size/strength of the bloom doesn't vary much with the resolution, otherwise
|
||||
@@ -1976,6 +2002,9 @@ PostProcessManager::BloomPassOutput PostProcessManager::bloomPass(FrameGraph& fg
|
||||
|
||||
bool threshold = inoutBloomOptions.threshold;
|
||||
|
||||
// we don't need to do the fireflies reduction if we have TAA (it already does it)
|
||||
bool fireflies = threshold && !taaOptions.enabled;
|
||||
|
||||
while (2 * bloomWidth < float(desc.width) || 2 * bloomHeight < float(desc.height)) {
|
||||
if (inoutBloomOptions.quality == QualityLevel::LOW ||
|
||||
inoutBloomOptions.quality == QualityLevel::MEDIUM) {
|
||||
@@ -1984,8 +2013,9 @@ PostProcessManager::BloomPassOutput PostProcessManager::bloomPass(FrameGraph& fg
|
||||
.height = (desc.height = std::max(1u, desc.height / 2)),
|
||||
.format = outFormat
|
||||
},
|
||||
threshold, inoutBloomOptions.highlight, threshold);
|
||||
threshold, inoutBloomOptions.highlight, fireflies);
|
||||
threshold = false; // we do the thresholding only once during down sampling
|
||||
fireflies = false; // we do the fireflies reduction only once during down sampling
|
||||
} else if (inoutBloomOptions.quality == QualityLevel::HIGH ||
|
||||
inoutBloomOptions.quality == QualityLevel::ULTRA) {
|
||||
// In high quality mode, we increase the size of the bloom buffer such that the
|
||||
@@ -2006,7 +2036,7 @@ PostProcessManager::BloomPassOutput PostProcessManager::bloomPass(FrameGraph& fg
|
||||
|
||||
input = downscalePass(fg, input,
|
||||
{ .width = width, .height = height, .format = outFormat },
|
||||
threshold, inoutBloomOptions.highlight, threshold);
|
||||
threshold, inoutBloomOptions.highlight, fireflies);
|
||||
|
||||
struct BloomPassData {
|
||||
FrameGraphId<FrameGraphTexture> out;
|
||||
@@ -2635,6 +2665,10 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
|
||||
auto& taaPass = fg.addPass<TAAData>("TAA",
|
||||
[&](FrameGraph::Builder& builder, auto& data) {
|
||||
auto desc = fg.getDescriptor(input);
|
||||
if (taaOptions.upscaling) {
|
||||
desc.width *= 2;
|
||||
desc.height *= 2;
|
||||
}
|
||||
data.color = builder.sample(input);
|
||||
data.depth = builder.sample(depth);
|
||||
data.history = builder.sample(colorHistory);
|
||||
@@ -2669,18 +2703,26 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
|
||||
{ -1.0f, 1.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f },
|
||||
};
|
||||
|
||||
float sum = 0.0;
|
||||
constexpr float2 subSampleOffsets[4] = {
|
||||
{ -0.25f, 0.25f }, { 0.25f, 0.25f }, { 0.25f, -0.25f }, { -0.25f, -0.25f }
|
||||
};
|
||||
|
||||
float4 sum = 0.0;
|
||||
float4 weights[9];
|
||||
|
||||
// this doesn't get vectorized (probably because of exp()), so don't bother
|
||||
// unrolling it.
|
||||
#pragma nounroll
|
||||
for (size_t i = 0; i < 9; i++) {
|
||||
float2 const d = (sampleOffsets[i] - current.jitter) / taaOptions.filterWidth;
|
||||
// This is a gaussian fit of a 3.3-wide Blackman-Harris window
|
||||
// see: "High Quality Temporal Supersampling" by Brian Karis
|
||||
weights[i][0] = std::exp(-2.29f * (d.x * d.x + d.y * d.y));
|
||||
sum += weights[i][0];
|
||||
float2 const o = sampleOffsets[i];
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
float2 const s = taaOptions.upscaling ? subSampleOffsets[j] : float2{ 0 };
|
||||
float2 const d = (o - current.jitter - s) / taaOptions.filterWidth;
|
||||
// This is a gaussian fit of a 3.3-wide Blackman-Harris window
|
||||
// see: "High Quality Temporal Supersampling" by Brian Karis
|
||||
weights[i][j] = std::exp(-2.29f * (d.x * d.x + d.y * d.y));
|
||||
}
|
||||
sum += weights[i];
|
||||
}
|
||||
for (auto& w : weights) {
|
||||
w /= sum;
|
||||
@@ -3149,7 +3191,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::vsmMipmapPass(FrameGraph& fg
|
||||
auto& material = getPostProcessMaterial("vsmMipmap");
|
||||
|
||||
// When generating shadow map mip levels, we want to preserve the 1 texel border.
|
||||
// (note clearing never respects the scissor in filament)
|
||||
// (note clearing never respects the scissor in Filament)
|
||||
PipelineState pipeline(material.getPipelineState(mEngine));
|
||||
pipeline.scissor = { 1u, 1u, dim - 2u, dim - 2u };
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ public:
|
||||
FrameGraphId<FrameGraphTexture> depth,
|
||||
const CameraInfo& cameraInfo,
|
||||
bool translucent,
|
||||
float bokehAspectRatio,
|
||||
math::float2 bokehScale,
|
||||
const DepthOfFieldOptions& dofOptions) noexcept;
|
||||
|
||||
// Bloom
|
||||
@@ -171,7 +171,9 @@ public:
|
||||
FrameGraphId<FrameGraphTexture> flare;
|
||||
};
|
||||
BloomPassOutput bloom(FrameGraph& fg, FrameGraphId<FrameGraphTexture> input,
|
||||
BloomOptions& inoutBloomOptions, backend::TextureFormat outFormat,
|
||||
backend::TextureFormat outFormat,
|
||||
BloomOptions& inoutBloomOptions,
|
||||
TemporalAntiAliasingOptions const& taaOptions,
|
||||
math::float2 scale) noexcept;
|
||||
|
||||
FrameGraphId<FrameGraphTexture> flarePass(FrameGraph& fg,
|
||||
@@ -342,10 +344,6 @@ private:
|
||||
math::int2 axis, float zf, backend::TextureFormat format,
|
||||
BilateralPassConfig const& config) noexcept;
|
||||
|
||||
BloomPassOutput bloomPass(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> input, backend::TextureFormat outFormat,
|
||||
BloomOptions& inoutBloomOptions, math::float2 scale) noexcept;
|
||||
|
||||
FrameGraphId<FrameGraphTexture> downscalePass(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> input,
|
||||
FrameGraphTexture::Descriptor const& outDesc,
|
||||
|
||||
@@ -117,7 +117,7 @@ void FMaterialInstance::initDefaultInstance(FEngine& engine, FMaterial const* ma
|
||||
if (!material->getSamplerInterfaceBlock().isEmpty()) {
|
||||
mSamplers = SamplerGroup(material->getSamplerInterfaceBlock().getSize());
|
||||
mSbHandle = driver.createSamplerGroup(
|
||||
mSamplers.getSize(), utils::FixedSizeString<32>("Default material"));
|
||||
mSamplers.getSize(), utils::FixedSizeString<32>(mMaterial->getName().c_str_safe()));
|
||||
}
|
||||
|
||||
const RasterState& rasterState = material->getRasterState();
|
||||
|
||||
@@ -495,6 +495,14 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
|
||||
// This configures post-process materials by setting constant parameters
|
||||
if (taaOptions.enabled) {
|
||||
ppm.configureTemporalAntiAliasingMaterial(taaOptions);
|
||||
if (taaOptions.upscaling) {
|
||||
// for now TAA upscaling is incompatible with regular dsr
|
||||
dsrOptions.enabled = false;
|
||||
// also, upscaling doesn't work well with quater-resolution SSAO
|
||||
aoOptions.resolution = 1.0;
|
||||
// Currently we only support a fixed TAA upscaling ratio
|
||||
scale = 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,7 +533,7 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
|
||||
};
|
||||
|
||||
// whether we're scaled at all
|
||||
const bool scaled = any(notEqual(scale, float2(1.0f)));
|
||||
bool scaled = any(notEqual(scale, float2(1.0f)));
|
||||
|
||||
// vp is the user defined viewport within the View
|
||||
filament::Viewport const& vp = view.getViewport();
|
||||
@@ -614,7 +622,7 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
|
||||
|
||||
view.prepare(engine, driver, arena, svp, cameraInfo, getShaderUserTime(), needsAlphaChannel);
|
||||
|
||||
view.prepareUpscaler(scale, dsrOptions);
|
||||
view.prepareUpscaler(scale, taaOptions, dsrOptions);
|
||||
|
||||
/*
|
||||
* Allocate command buffer
|
||||
@@ -1011,6 +1019,15 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
|
||||
if (taaOptions.enabled) {
|
||||
input = ppm.taa(fg, input, depth, view.getFrameHistory(), &FrameHistoryEntry::taa,
|
||||
taaOptions, colorGradingConfig);
|
||||
if (taaOptions.upscaling) {
|
||||
scale = 1.0f;
|
||||
scaled = false;
|
||||
UTILS_UNUSED_IN_RELEASE auto const& inputDesc = fg.getDescriptor(input);
|
||||
svp.width = inputDesc.width;
|
||||
svp.height = inputDesc.height;
|
||||
xvp.width *= 2;
|
||||
xvp.height *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
@@ -1026,16 +1043,21 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
|
||||
// The bokeh height is always correct regardless of the dynamic resolution scaling.
|
||||
// (because the CoC is calculated w.r.t. the height), so we only need to adjust
|
||||
// the width.
|
||||
float const bokehAspectRatio = scale.x / scale.y;
|
||||
float const aspect = (scale.x / scale.y) * dofOptions.cocAspectRatio;
|
||||
float2 const bokehScale{
|
||||
aspect < 1.0f ? aspect : 1.0f,
|
||||
aspect > 1.0f ? 1.0f / aspect : 1.0f
|
||||
};
|
||||
input = ppm.dof(fg, input, depth, cameraInfo, needsAlphaChannel,
|
||||
bokehAspectRatio, dofOptions);
|
||||
bokehScale, dofOptions);
|
||||
}
|
||||
|
||||
FrameGraphId<FrameGraphTexture> bloom, flare;
|
||||
if (bloomOptions.enabled) {
|
||||
// Generate the bloom buffer, which is stored in the blackboard as "bloom". This is
|
||||
// consumed by the colorGrading pass and will be culled if colorGrading is disabled.
|
||||
auto [bloom_, flare_] = ppm.bloom(fg, input, bloomOptions, TextureFormat::R11F_G11F_B10F, scale);
|
||||
auto [bloom_, flare_] = ppm.bloom(fg, input, TextureFormat::R11F_G11F_B10F,
|
||||
bloomOptions, taaOptions, scale);
|
||||
bloom = bloom_;
|
||||
flare = flare_;
|
||||
}
|
||||
|
||||
@@ -725,11 +725,22 @@ UTILS_NOINLINE
|
||||
});
|
||||
}
|
||||
|
||||
void FView::prepareUpscaler(float2 scale, DynamicResolutionOptions const& options) const noexcept {
|
||||
void FView::prepareUpscaler(float2 scale,
|
||||
TemporalAntiAliasingOptions const& taaOptions,
|
||||
DynamicResolutionOptions const& dsrOptions) const noexcept {
|
||||
SYSTRACE_CALL();
|
||||
const float bias = (options.quality >= QualityLevel::HIGH) ?
|
||||
std::log2(std::min(scale.x, scale.y)) : 0.0f;
|
||||
mPerViewUniforms.prepareLodBias(bias);
|
||||
float bias = 0.0f;
|
||||
float2 derivativesScale{ 1.0f };
|
||||
if (dsrOptions.enabled && dsrOptions.quality >= QualityLevel::HIGH) {
|
||||
bias = std::log2(std::min(scale.x, scale.y));
|
||||
}
|
||||
if (taaOptions.enabled) {
|
||||
bias += taaOptions.lodBias;
|
||||
if (taaOptions.upscaling) {
|
||||
derivativesScale = 0.5f;
|
||||
}
|
||||
}
|
||||
mPerViewUniforms.prepareLodBias(bias, derivativesScale);
|
||||
}
|
||||
|
||||
void FView::prepareCamera(FEngine& engine, const CameraInfo& cameraInfo) const noexcept {
|
||||
|
||||
@@ -133,7 +133,9 @@ public:
|
||||
return mName.c_str_safe();
|
||||
}
|
||||
|
||||
void prepareUpscaler(math::float2 scale, DynamicResolutionOptions const& options) const noexcept;
|
||||
void prepareUpscaler(math::float2 scale,
|
||||
TemporalAntiAliasingOptions const& taaOptions,
|
||||
DynamicResolutionOptions const& dsrOptions) const noexcept;
|
||||
void prepareCamera(FEngine& engine, const CameraInfo& cameraInfo) const noexcept;
|
||||
|
||||
void prepareViewport(
|
||||
|
||||
@@ -240,7 +240,8 @@ void postProcess(inout PostProcessInputs postProcess) {
|
||||
history.rgb = RGB_YCoCg(history.rgb);
|
||||
}
|
||||
|
||||
highp vec2 p = uv.xy;
|
||||
highp vec2 size = vec2(textureSize(materialParams_color, 0));
|
||||
highp vec2 p = (floor(uv.xy * size) + 0.5) / size;
|
||||
vec4 color = textureLod(materialParams_color, p, 0.0);
|
||||
|
||||
vec3 s[9];
|
||||
@@ -265,15 +266,25 @@ void postProcess(inout PostProcessInputs postProcess) {
|
||||
}
|
||||
}
|
||||
|
||||
vec4 filtered;
|
||||
vec2 subPixelOffset = p - uv.xy; // +/- [0.25, 0.25]
|
||||
float confidence = 0.0;
|
||||
|
||||
vec4 filtered = color;
|
||||
if (materialConstants_filterInput) {
|
||||
// unjitter/filter input
|
||||
// figure out which set of coeficients to use
|
||||
int jxp = subPixelOffset.y > 0.0 ? 3 : 0;
|
||||
int jxn = subPixelOffset.y > 0.0 ? 2 : 1;
|
||||
int j = subPixelOffset.x > 0.0 ? jxp : jxn;
|
||||
filtered = vec4(0, 0, 0, color.a);
|
||||
for (int i = 0; i < 9; i++) {
|
||||
filtered.rgb += s[i] * materialParams.filterWeights[i][0];
|
||||
float w = materialParams.filterWeights[i][j];
|
||||
filtered.rgb += s[i] * w;
|
||||
confidence = max(confidence, w);
|
||||
}
|
||||
} else {
|
||||
filtered = color;
|
||||
confidence = float(materialParams.jitter.x * subPixelOffset.x > 0.0 &&
|
||||
materialParams.jitter.y * subPixelOffset.y > 0.0);
|
||||
}
|
||||
|
||||
// build the history clamping box
|
||||
@@ -321,7 +332,7 @@ void postProcess(inout PostProcessInputs postProcess) {
|
||||
float lumaColor = luma(filtered.rgb);
|
||||
float lumaHistory = luma(history.rgb);
|
||||
|
||||
float alpha = materialParams.alpha;
|
||||
float alpha = materialParams.alpha * confidence;
|
||||
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));
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Filament"
|
||||
spec.version = "1.49.2"
|
||||
spec.version = "1.49.3"
|
||||
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
|
||||
spec.homepage = "https://google.github.io/filament"
|
||||
spec.authors = "Google LLC."
|
||||
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
|
||||
spec.platform = :ios, "11.0"
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.49.2/filament-v1.49.2-ios.tgz" }
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.49.3/filament-v1.49.3-ios.tgz" }
|
||||
|
||||
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
|
||||
spec.pod_target_xcconfig = {
|
||||
|
||||
@@ -47,6 +47,9 @@ const float kToastDelayDuration = 2.0f;
|
||||
- (void)createRenderables;
|
||||
- (void)createLights;
|
||||
|
||||
- (void)appWillResignActive:(NSNotification*)notification;
|
||||
- (void)appDidBecomeActive:(NSNotification*)notification;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FILViewController {
|
||||
@@ -73,6 +76,16 @@ const float kToastDelayDuration = 2.0f;
|
||||
|
||||
self.title = @"https://google.github.io/filament/remote";
|
||||
|
||||
// Observe lifecycle notifications to prevent us from rendering in the background.
|
||||
[NSNotificationCenter.defaultCenter addObserver:self
|
||||
selector:@selector(appWillResignActive:)
|
||||
name:UIApplicationWillResignActiveNotification
|
||||
object:nil];
|
||||
[NSNotificationCenter.defaultCenter addObserver:self
|
||||
selector:@selector(appDidBecomeActive:)
|
||||
name:UIApplicationDidBecomeActiveNotification
|
||||
object:nil];
|
||||
|
||||
// Arguments:
|
||||
// --model <path>
|
||||
// path to glb or gltf file to load from documents directory
|
||||
@@ -125,6 +138,14 @@ const float kToastDelayDuration = 2.0f;
|
||||
[self.view addSubview:_toastLabel];
|
||||
}
|
||||
|
||||
- (void)appWillResignActive:(NSNotification*)notification {
|
||||
[self stopDisplayLink];
|
||||
}
|
||||
|
||||
- (void)appDidBecomeActive:(NSNotification*)notification {
|
||||
[self startDisplayLink];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[self startDisplayLink];
|
||||
}
|
||||
@@ -330,6 +351,7 @@ const float kToastDelayDuration = 2.0f;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[NSNotificationCenter.defaultCenter removeObserver:self];
|
||||
delete _server;
|
||||
delete _automation;
|
||||
self.modelView.engine->destroy(_indirectLight);
|
||||
|
||||
@@ -99,6 +99,7 @@ struct PerViewUib { // NOLINT(cppcoreguidelines-pro-type-member-init)
|
||||
|
||||
float lodBias; // load bias to apply to user materials
|
||||
float refractionLodOffset;
|
||||
math::float2 derivativesScale;
|
||||
|
||||
// camera position in view space (when camera_at_origin is enabled), i.e. it's (0,0,0).
|
||||
float oneOverFarMinusNear; // 1 / (f-n), always positive
|
||||
@@ -111,8 +112,6 @@ struct PerViewUib { // NOLINT(cppcoreguidelines-pro-type-member-init)
|
||||
// AO
|
||||
float aoSamplingQualityAndEdgeDistance; // <0: no AO, 0: bilinear, !0: bilateral edge distance
|
||||
float aoBentNormals; // 0: no AO bent normal, >0.0 AO bent normals
|
||||
float aoReserved0;
|
||||
float aoReserved1;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Dynamic Lighting [variant: DYN]
|
||||
|
||||
@@ -1168,7 +1168,6 @@ error:
|
||||
mVariantFilter |= uint32_t(UserVariantFilterBit::SHADOW_RECEIVER);
|
||||
mVariantFilter |= uint32_t(UserVariantFilterBit::VSM);
|
||||
mVariantFilter |= uint32_t(UserVariantFilterBit::SSR);
|
||||
mVariantFilter |= uint32_t(UserVariantFilterBit::STE);
|
||||
}
|
||||
|
||||
// Create chunk tree.
|
||||
|
||||
@@ -52,7 +52,7 @@ void ShaderGenerator::generateSurfaceMaterialVariantDefines(utils::io::sstream&
|
||||
CodeGenerator::generateDefine(out, "VARIANT_HAS_VSM",
|
||||
filament::Variant::isVSMVariant(variant));
|
||||
CodeGenerator::generateDefine(out, "VARIANT_HAS_INSTANCED_STEREO",
|
||||
filament::Variant::isStereoVariant(variant));
|
||||
hasInstancedStereo(variant, featureLevel));
|
||||
|
||||
switch (stage) {
|
||||
case ShaderStage::VERTEX:
|
||||
@@ -758,4 +758,12 @@ bool ShaderGenerator::hasSkinningOrMorphing(
|
||||
&& featureLevel > MaterialBuilder::FeatureLevel::FEATURE_LEVEL_0;
|
||||
}
|
||||
|
||||
bool ShaderGenerator::hasInstancedStereo(
|
||||
filament::Variant variant, MaterialBuilder::FeatureLevel featureLevel) noexcept {
|
||||
return variant.hasInstancedStereo()
|
||||
// HACK(exv): Ignore stereo variant when targeting ESSL 1.0. We should properly build a
|
||||
// system in matc which allows the set of included variants to differ per-feature level.
|
||||
&& featureLevel > MaterialBuilder::FeatureLevel::FEATURE_LEVEL_0;
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -115,6 +115,10 @@ private:
|
||||
filament::Variant variant,
|
||||
MaterialBuilder::FeatureLevel featureLevel) noexcept;
|
||||
|
||||
static bool hasInstancedStereo(
|
||||
filament::Variant variant,
|
||||
MaterialBuilder::FeatureLevel featureLevel) noexcept;
|
||||
|
||||
MaterialBuilder::PropertyList mProperties;
|
||||
MaterialBuilder::VariableList mVariables;
|
||||
MaterialBuilder::OutputList mOutputs;
|
||||
|
||||
@@ -60,6 +60,7 @@ BufferInterfaceBlock const& UibGenerator::getPerViewUib() noexcept {
|
||||
|
||||
{ "lodBias", 0, Type::FLOAT, Precision::DEFAULT, FeatureLevel::FEATURE_LEVEL_0 },
|
||||
{ "refractionLodOffset", 0, Type::FLOAT, Precision::DEFAULT, FeatureLevel::FEATURE_LEVEL_0 },
|
||||
{ "derivativesScale", 0, Type::FLOAT2 },
|
||||
|
||||
{ "oneOverFarMinusNear", 0, Type::FLOAT, Precision::HIGH, FeatureLevel::FEATURE_LEVEL_0 },
|
||||
{ "nearOverFarMinusNear", 0, Type::FLOAT, Precision::HIGH, FeatureLevel::FEATURE_LEVEL_0 },
|
||||
@@ -71,8 +72,6 @@ BufferInterfaceBlock const& UibGenerator::getPerViewUib() noexcept {
|
||||
// AO
|
||||
{ "aoSamplingQualityAndEdgeDistance", 0, Type::FLOAT },
|
||||
{ "aoBentNormals", 0, Type::FLOAT },
|
||||
{ "aoReserved0", 0, Type::FLOAT },
|
||||
{ "aoReserved1", 0, Type::FLOAT },
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Dynamic Lighting [variant: DYN]
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
margin: 0;
|
||||
font-family: "Open Sans";
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: codicon;
|
||||
src: url(https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.25.2/min/vs/base/browser/ui/codicons/codicon/codicon.ttf);
|
||||
}
|
||||
</style>
|
||||
<script src="api.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.25.2/min/vs/loader.js"></script>
|
||||
|
||||
@@ -111,7 +111,7 @@ private:
|
||||
friend ostream& hex(ostream& s) noexcept;
|
||||
friend ostream& dec(ostream& s) noexcept;
|
||||
friend ostream& endl(ostream& s) noexcept;
|
||||
friend ostream& flush(ostream& s) noexcept;
|
||||
UTILS_PUBLIC friend ostream& flush(ostream& s) noexcept;
|
||||
|
||||
enum type {
|
||||
SHORT, USHORT, CHAR, UCHAR, INT, UINT, LONG, ULONG, LONG_LONG, ULONG_LONG, FLOAT, DOUBLE,
|
||||
|
||||
@@ -391,6 +391,8 @@ int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, DepthOfFieldOpt
|
||||
CHECK_KEY(tok);
|
||||
if (compare(tok, jsonChunk, "cocScale") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->cocScale);
|
||||
} else if (compare(tok, jsonChunk, "cocAspectRatio") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->cocAspectRatio);
|
||||
} else if (compare(tok, jsonChunk, "maxApertureDiameter") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->maxApertureDiameter);
|
||||
} else if (compare(tok, jsonChunk, "enabled") == 0) {
|
||||
@@ -424,6 +426,7 @@ int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, DepthOfFieldOpt
|
||||
std::ostream& operator<<(std::ostream& out, const DepthOfFieldOptions& in) {
|
||||
return out << "{\n"
|
||||
<< "\"cocScale\": " << (in.cocScale) << ",\n"
|
||||
<< "\"cocAspectRatio\": " << (in.cocAspectRatio) << ",\n"
|
||||
<< "\"maxApertureDiameter\": " << (in.maxApertureDiameter) << ",\n"
|
||||
<< "\"enabled\": " << to_string(in.enabled) << ",\n"
|
||||
<< "\"filter\": " << (in.filter) << ",\n"
|
||||
@@ -716,8 +719,12 @@ int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, TemporalAntiAli
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->filterWidth);
|
||||
} else if (compare(tok, jsonChunk, "feedback") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->feedback);
|
||||
} else if (compare(tok, jsonChunk, "lodBias") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->lodBias);
|
||||
} else if (compare(tok, jsonChunk, "enabled") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->enabled);
|
||||
} else if (compare(tok, jsonChunk, "upscaling") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->upscaling);
|
||||
} else if (compare(tok, jsonChunk, "filterHistory") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->filterHistory);
|
||||
} else if (compare(tok, jsonChunk, "filterInput") == 0) {
|
||||
@@ -752,7 +759,9 @@ std::ostream& operator<<(std::ostream& out, const TemporalAntiAliasingOptions& i
|
||||
return out << "{\n"
|
||||
<< "\"filterWidth\": " << (in.filterWidth) << ",\n"
|
||||
<< "\"feedback\": " << (in.feedback) << ",\n"
|
||||
<< "\"lodBias\": " << (in.lodBias) << ",\n"
|
||||
<< "\"enabled\": " << to_string(in.enabled) << ",\n"
|
||||
<< "\"upscaling\": " << to_string(in.upscaling) << ",\n"
|
||||
<< "\"filterHistory\": " << to_string(in.filterHistory) << ",\n"
|
||||
<< "\"filterInput\": " << to_string(in.filterInput) << ",\n"
|
||||
<< "\"useYCoCg\": " << to_string(in.useYCoCg) << ",\n"
|
||||
|
||||
@@ -793,11 +793,13 @@ void ViewerGui::updateUserInterface() {
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("TAA Options")) {
|
||||
ImGui::Checkbox("Upscaling", &mSettings.view.taa.upscaling);
|
||||
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.2f, 2.0f);
|
||||
ImGui::SliderFloat("LOD bias", &mSettings.view.taa.lodBias, -8.0f, 0.0f);
|
||||
ImGui::Checkbox("Use YCoCg", &mSettings.view.taa.useYCoCg);
|
||||
ImGui::Checkbox("Prevent Flickering", &mSettings.view.taa.preventFlickering);
|
||||
int jitterSequence = (int)mSettings.view.taa.jitterPattern;
|
||||
@@ -1034,6 +1036,7 @@ void ViewerGui::updateUserInterface() {
|
||||
ImGui::Checkbox("Enabled##dofEnabled", &mSettings.view.dof.enabled);
|
||||
ImGui::SliderFloat("Focus distance", &mSettings.viewer.cameraFocusDistance, 0.0f, 30.0f);
|
||||
ImGui::SliderFloat("Blur scale", &mSettings.view.dof.cocScale, 0.1f, 10.0f);
|
||||
ImGui::SliderFloat("CoC aspect-ratio", &mSettings.view.dof.cocAspectRatio, 0.25f, 4.0f);
|
||||
ImGui::SliderInt("Ring count", &dofRingCount, 1, 17);
|
||||
ImGui::SliderInt("Max CoC", &dofMaxCoC, 1, 32);
|
||||
ImGui::Checkbox("Native Resolution", &mSettings.view.dof.nativeResolution);
|
||||
|
||||
@@ -37,8 +37,11 @@ float normalFiltering(float perceptualRoughness, const vec3 worldNormal) {
|
||||
vec3 du = dFdx(worldNormal);
|
||||
vec3 dv = dFdy(worldNormal);
|
||||
|
||||
float variance = materialParams._specularAntiAliasingVariance * (dot(du, du) + dot(dv, dv));
|
||||
// specular AA factor to correct for resolution scaling (DSR and TAAx4)
|
||||
du *= frameUniforms.derivativesScale.x;
|
||||
dv *= frameUniforms.derivativesScale.y;
|
||||
|
||||
float variance = materialParams._specularAntiAliasingVariance * (dot(du, du) + dot(dv, dv));
|
||||
float roughness = perceptualRoughnessToRoughness(perceptualRoughness);
|
||||
float kernelRoughness = min(2.0 * variance, materialParams._specularAntiAliasingThreshold);
|
||||
float squareRoughness = saturate(roughness * roughness + kernelRoughness);
|
||||
|
||||
@@ -27,9 +27,7 @@ JsonType JsonishLexer::readIdentifier() noexcept {
|
||||
consume();
|
||||
}
|
||||
|
||||
const char* lexemeEnd = mCursor - 1;
|
||||
|
||||
size_t lexemeSize = lexemeEnd - lexemeStart;
|
||||
size_t lexemeSize = mCursor - lexemeStart;
|
||||
|
||||
// Check what kind of keyword we got here.
|
||||
if (strncmp("true", lexemeStart, lexemeSize) == 0) {
|
||||
|
||||
@@ -229,7 +229,7 @@ static bool reflectParameters(const MaterialBuilder& builder) {
|
||||
std::cout << R"( "format": ")" <<
|
||||
Enums::toString(parameter.format) << "\"," << std::endl;
|
||||
std::cout << R"( "precision": ")" <<
|
||||
Enums::toString(parameter.precision) << "\"" << std::endl;
|
||||
Enums::toString(parameter.precision) << "\"," << std::endl;
|
||||
std::cout << R"( "multisample": ")" <<
|
||||
(parameter.multisample ? "true" : "false")<< "\"" << std::endl;
|
||||
} else if (parameter.isUniform()) {
|
||||
|
||||
@@ -60,6 +60,7 @@ Filament.loadGeneratedExtensions = function() {
|
||||
Filament.View.prototype.setDepthOfFieldOptionsDefaults = function(overrides) {
|
||||
const options = {
|
||||
cocScale: 1.0,
|
||||
cocAspectRatio: 1.0,
|
||||
maxApertureDiameter: 0.01,
|
||||
enabled: false,
|
||||
filter: Filament.View$DepthOfFieldOptions$Filter.MEDIAN,
|
||||
@@ -139,7 +140,9 @@ Filament.loadGeneratedExtensions = function() {
|
||||
const options = {
|
||||
filterWidth: 1.0,
|
||||
feedback: 0.12,
|
||||
lodBias: -1.0,
|
||||
enabled: false,
|
||||
upscaling: false,
|
||||
filterHistory: true,
|
||||
filterInput: true,
|
||||
useYCoCg: false,
|
||||
|
||||
14
web/filament-js/filament.d.ts
vendored
14
web/filament-js/filament.d.ts
vendored
@@ -1409,6 +1409,10 @@ export interface View$DepthOfFieldOptions {
|
||||
* circle of confusion scale factor (amount of blur)
|
||||
*/
|
||||
cocScale?: number;
|
||||
/**
|
||||
* width/height aspect ratio of the circle of confusion (simulate anamorphic lenses)
|
||||
*/
|
||||
cocAspectRatio?: number;
|
||||
/**
|
||||
* maximum aperture diameter in meters (zero to disable rotation)
|
||||
*/
|
||||
@@ -1659,7 +1663,7 @@ export enum View$TemporalAntiAliasingOptions$JitterPattern {
|
||||
* 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`, `feedback` and `jitterPattern`, however, can be changed at any time.
|
||||
* `filterWidth`, `feedback` and `jitterPattern`, however, could be changed at any time.
|
||||
*
|
||||
* `feedback` of 0.1 effectively accumulates a maximum of 19 samples in steady state.
|
||||
* see "A Survey of Temporal Antialiasing Techniques" by Lei Yang and all for more information.
|
||||
@@ -1675,10 +1679,18 @@ export interface View$TemporalAntiAliasingOptions {
|
||||
* history feedback, between 0 (maximum temporal AA) and 1 (no temporal AA).
|
||||
*/
|
||||
feedback?: number;
|
||||
/**
|
||||
* texturing lod bias (typically -1 or -2)
|
||||
*/
|
||||
lodBias?: number;
|
||||
/**
|
||||
* enables or disables temporal anti-aliasing
|
||||
*/
|
||||
enabled?: boolean;
|
||||
/**
|
||||
* 4x TAA upscaling. Disables Dynamic Resolution. [BETA]
|
||||
*/
|
||||
upscaling?: boolean;
|
||||
/**
|
||||
* whether to filter the history buffer
|
||||
*/
|
||||
|
||||
@@ -58,6 +58,7 @@ value_object<View::FogOptions>("View$FogOptions")
|
||||
|
||||
value_object<View::DepthOfFieldOptions>("View$DepthOfFieldOptions")
|
||||
.field("cocScale", &View::DepthOfFieldOptions::cocScale)
|
||||
.field("cocAspectRatio", &View::DepthOfFieldOptions::cocAspectRatio)
|
||||
.field("maxApertureDiameter", &View::DepthOfFieldOptions::maxApertureDiameter)
|
||||
.field("enabled", &View::DepthOfFieldOptions::enabled)
|
||||
.field("filter", &View::DepthOfFieldOptions::filter)
|
||||
@@ -119,7 +120,9 @@ value_object<View::MultiSampleAntiAliasingOptions>("View$MultiSampleAntiAliasing
|
||||
value_object<View::TemporalAntiAliasingOptions>("View$TemporalAntiAliasingOptions")
|
||||
.field("filterWidth", &View::TemporalAntiAliasingOptions::filterWidth)
|
||||
.field("feedback", &View::TemporalAntiAliasingOptions::feedback)
|
||||
.field("lodBias", &View::TemporalAntiAliasingOptions::lodBias)
|
||||
.field("enabled", &View::TemporalAntiAliasingOptions::enabled)
|
||||
.field("upscaling", &View::TemporalAntiAliasingOptions::upscaling)
|
||||
.field("filterHistory", &View::TemporalAntiAliasingOptions::filterHistory)
|
||||
.field("filterInput", &View::TemporalAntiAliasingOptions::filterInput)
|
||||
.field("useYCoCg", &View::TemporalAntiAliasingOptions::useYCoCg)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "filament",
|
||||
"version": "1.49.2",
|
||||
"version": "1.49.3",
|
||||
"description": "Real-time physically based rendering engine",
|
||||
"main": "filament.js",
|
||||
"module": "filament.js",
|
||||
|
||||
@@ -203,7 +203,9 @@ set(HTML_FILES
|
||||
skinning.html
|
||||
suzanne.html
|
||||
test-filament-viewer.html
|
||||
triangle.html)
|
||||
triangle.html
|
||||
benchmark-shader-compilation.html
|
||||
benchmark-shader-compilation.js)
|
||||
|
||||
set(ASSET_FILES
|
||||
assets/favicon.png)
|
||||
|
||||
22
web/samples/benchmark-shader-compilation.html
Normal file
22
web/samples/benchmark-shader-compilation.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Shader Compilation Benchmark</title>
|
||||
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1">
|
||||
<style>
|
||||
body { margin: 0; overflow: hidden; }
|
||||
canvas { touch-action: none; width: 100%; height: 100%; }
|
||||
.frame-time { position: absolute; color: #ffffff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="frame-time">
|
||||
Average Frame Time: <span id="frame-time-counter">Calculating...</span>
|
||||
</div>
|
||||
<canvas></canvas>
|
||||
<script src="filament.js"></script>
|
||||
<script src="gl-matrix-min.js"></script>
|
||||
<script src="benchmark-shader-compilation.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
141
web/samples/benchmark-shader-compilation.js
Normal file
141
web/samples/benchmark-shader-compilation.js
Normal file
@@ -0,0 +1,141 @@
|
||||
Filament.init(['nonlit.filamat'], () => {
|
||||
window.VertexAttribute = Filament.VertexAttribute;
|
||||
window.AttributeType = Filament.VertexBuffer$AttributeType;
|
||||
window.Projection = Filament.Camera$Projection;
|
||||
window.app = new App(
|
||||
document.getElementsByTagName('canvas')[0],
|
||||
document.getElementById('frame-time-counter'));
|
||||
});
|
||||
|
||||
const NUMBER_OF_TRIANGLES = 100;
|
||||
// probably 60 fps; record 1 seconds ish worth of frames.
|
||||
const NUMBER_OF_FRAMES_TO_RECORD_FPS = 1 * 60;
|
||||
|
||||
class App {
|
||||
constructor(canvas, frameTimeCounter) {
|
||||
this.canvas = canvas;
|
||||
this.frameTimeCounter = frameTimeCounter;
|
||||
|
||||
this.lastFrameTime = null;
|
||||
this.frameDeltas = [];
|
||||
for (let i = 0; i < NUMBER_OF_FRAMES_TO_RECORD_FPS; ++i) {
|
||||
this.frameDeltas.push(0);
|
||||
}
|
||||
this.frameDeltasIndex = 0;
|
||||
this.frameDeltasSum = 0;
|
||||
this.frameTimeIsValid = false;
|
||||
|
||||
const engine = this.engine = Filament.Engine.create(this.canvas);
|
||||
this.scene = engine.createScene();
|
||||
this.triangles = [];
|
||||
for (let i = 0; i < NUMBER_OF_TRIANGLES; ++i) {
|
||||
const entity = Filament.EntityManager.get().create();
|
||||
this.triangles.push({entity: entity});
|
||||
this.scene.addEntity(entity);
|
||||
}
|
||||
|
||||
const TRIANGLE_POSITIONS = new Float32Array([
|
||||
1,
|
||||
0,
|
||||
Math.cos(Math.PI * 2 / 3),
|
||||
Math.sin(Math.PI * 2 / 3),
|
||||
Math.cos(Math.PI * 4 / 3),
|
||||
Math.sin(Math.PI * 4 / 3),
|
||||
]);
|
||||
|
||||
const TRIANGLE_COLORS =
|
||||
new Uint32Array([0xffff0000, 0xff00ff00, 0xff0000ff]);
|
||||
|
||||
this.vb =
|
||||
Filament.VertexBuffer.Builder()
|
||||
.vertexCount(3)
|
||||
.bufferCount(2)
|
||||
.attribute(VertexAttribute.POSITION, 0, AttributeType.FLOAT2, 0, 8)
|
||||
.attribute(VertexAttribute.COLOR, 1, AttributeType.UBYTE4, 0, 4)
|
||||
.normalized(VertexAttribute.COLOR)
|
||||
.build(engine);
|
||||
|
||||
this.vb.setBufferAt(engine, 0, TRIANGLE_POSITIONS);
|
||||
this.vb.setBufferAt(engine, 1, TRIANGLE_COLORS);
|
||||
|
||||
this.ib = Filament.IndexBuffer.Builder()
|
||||
.indexCount(3)
|
||||
.bufferType(Filament.IndexBuffer$IndexType.USHORT)
|
||||
.build(engine);
|
||||
|
||||
this.ib.setBuffer(engine, new Uint16Array([0, 1, 2]));
|
||||
|
||||
this.swapChain = engine.createSwapChain();
|
||||
this.renderer = engine.createRenderer();
|
||||
this.camera = engine.createCamera(Filament.EntityManager.get().create());
|
||||
|
||||
this.view = engine.createView();
|
||||
this.view.setSampleCount(4);
|
||||
this.view.setCamera(this.camera);
|
||||
this.view.setScene(this.scene);
|
||||
|
||||
this.renderer.setClearOptions(
|
||||
{clearColor: [0.0, 0.1, 0.2, 1.0], clear: true});
|
||||
|
||||
this.resize();
|
||||
this.render = this.render.bind(this);
|
||||
this.resize = this.resize.bind(this);
|
||||
window.addEventListener('resize', this.resize);
|
||||
window.requestAnimationFrame(this.render);
|
||||
}
|
||||
|
||||
render() {
|
||||
const frameTime = Date.now();
|
||||
if (this.lastFrameTime) {
|
||||
const delta = frameTime - this.lastFrameTime;
|
||||
this.frameDeltasSum =
|
||||
this.frameDeltasSum - this.frameDeltas[this.frameDeltasIndex] + delta;
|
||||
this.frameDeltas[this.frameDeltasIndex] = delta;
|
||||
this.frameDeltasIndex =
|
||||
(this.frameDeltasIndex + 1) % NUMBER_OF_FRAMES_TO_RECORD_FPS;
|
||||
if (this.frameDeltasIndex == 0) {
|
||||
this.frameTimeIsValid = true;
|
||||
}
|
||||
}
|
||||
this.lastFrameTime = frameTime;
|
||||
|
||||
if (this.frameTimeIsValid) {
|
||||
const averageFrameDelta =
|
||||
this.frameDeltasSum * 1.0 / NUMBER_OF_FRAMES_TO_RECORD_FPS;
|
||||
this.frameTimeCounter.innerHTML = averageFrameDelta.toFixed(2) + ' ms';
|
||||
}
|
||||
|
||||
this.triangles.forEach(triangle => {
|
||||
if (triangle.mat) {
|
||||
this.engine.destroyMaterial(triangle.mat);
|
||||
}
|
||||
triangle.mat = this.engine.createMaterial('nonlit.filamat');
|
||||
const matinst = triangle.mat.getDefaultInstance();
|
||||
Filament.RenderableManager.Builder(1)
|
||||
.boundingBox({center: [-1, -1, -1], halfExtent: [1, 1, 1]})
|
||||
.material(0, matinst)
|
||||
.geometry(
|
||||
0, Filament.RenderableManager$PrimitiveType.TRIANGLES, this.vb,
|
||||
this.ib)
|
||||
.build(this.engine, triangle.entity);
|
||||
});
|
||||
|
||||
const radians = Date.now() / 1000;
|
||||
const transform = mat4.fromRotation(mat4.create(), radians, [0, 0, 1]);
|
||||
const tcm = this.engine.getTransformManager();
|
||||
const inst = tcm.getInstance(this.triangles[0].entity);
|
||||
tcm.setTransform(inst, transform);
|
||||
inst.delete();
|
||||
this.renderer.render(this.swapChain, this.view);
|
||||
window.requestAnimationFrame(this.render);
|
||||
}
|
||||
|
||||
resize() {
|
||||
const dpr = window.devicePixelRatio;
|
||||
const width = this.canvas.width = window.innerWidth * dpr;
|
||||
const height = this.canvas.height = window.innerHeight * dpr;
|
||||
this.view.setViewport([0, 0, width, height]);
|
||||
const aspect = width / height;
|
||||
this.camera.setProjection(Projection.ORTHO, -aspect, aspect, -1, 1, 0, 1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user