From 385a17b8a5005d438c627d31b842d351a7e6cf56 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 31 Mar 2021 17:47:10 -0700 Subject: [PATCH] DoF: add many user settings - native/half resolution - gather kernel ring counts - circle-of-confusion radius clamps --- .../filament-android/src/main/cpp/View.cpp | 13 +++- .../com/google/android/filament/View.java | 59 ++++++++++++++++++- filament/CMakeLists.txt | 5 ++ filament/include/filament/View.h | 47 +++++++++++++-- filament/src/PostProcessManager.cpp | 19 +++++- filament/src/materials/dof/dof.mat | 52 ++++++++-------- filament/src/materials/dof/dofCoc.mat | 6 +- filament/src/materials/dof/dofDownsample.mat | 6 +- libs/viewer/src/Settings.cpp | 26 +++++++- libs/viewer/src/SimpleViewer.cpp | 23 ++++++-- web/filament-js/jsbindings.cpp | 8 ++- 11 files changed, 218 insertions(+), 46 deletions(-) diff --git a/android/filament-android/src/main/cpp/View.cpp b/android/filament-android/src/main/cpp/View.cpp index 541adb0eed..bdad7b0fae 100644 --- a/android/filament-android/src/main/cpp/View.cpp +++ b/android/filament-android/src/main/cpp/View.cpp @@ -300,7 +300,9 @@ Java_com_google_android_filament_View_nSetBlendMode(JNIEnv *, jclass , jlong nat extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_View_nSetDepthOfFieldOptions(JNIEnv *, jclass , - jlong nativeView, jfloat focusDistance, jfloat cocScale, jfloat maxApertureDiameter, jboolean enabled, jint filter) { + jlong nativeView, jfloat focusDistance, jfloat cocScale, jfloat maxApertureDiameter, jboolean enabled, jint filter, + jboolean nativeResolution, jint foregroundRingCount, jint backgroundRingCount, jint fastGatherRingCount, + jint maxForegroundCOC, jint maxBackgroundCOC) { View* view = (View*) nativeView; View::DepthOfFieldOptions::Filter eFilter{}; if (filter == 1) { @@ -308,7 +310,14 @@ Java_com_google_android_filament_View_nSetDepthOfFieldOptions(JNIEnv *, jclass , eFilter = View::DepthOfFieldOptions::Filter::MEDIAN; } view->setDepthOfFieldOptions({.focusDistance = focusDistance, .cocScale = cocScale, - .maxApertureDiameter = maxApertureDiameter, .enabled = (bool)enabled, .filter = eFilter}); + .maxApertureDiameter = maxApertureDiameter, .enabled = (bool)enabled, .filter = eFilter, + .nativeResolution = (bool)nativeResolution, + .foregroundRingCount = (uint8_t)foregroundRingCount, + .backgroundRingCount = (uint8_t)backgroundRingCount, + .fastGatherRingCount = (uint8_t)fastGatherRingCount, + .maxForegroundCOC = (uint8_t)maxForegroundCOC, + .maxBackgroundCOC = (uint8_t)maxBackgroundCOC, + }); } extern "C" diff --git a/android/filament-android/src/main/java/com/google/android/filament/View.java b/android/filament-android/src/main/java/com/google/android/filament/View.java index ab12538005..8affc43ca9 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/View.java +++ b/android/filament-android/src/main/java/com/google/android/filament/View.java @@ -266,7 +266,7 @@ public class View { /** * Options for Temporal Anti-aliasing (TAA) - * @see View#setTemporalAntiAliasingOptions() + * @see View#setTemporalAntiAliasingOptions */ public static class TemporalAntiAliasingOptions { /** reconstruction filter width typically between 0 (sharper, aliased) and 1 (smoother) */ @@ -465,6 +465,55 @@ public class View { /** filter to use for filling gaps in the kernel */ @NonNull public Filter filter = Filter.MEDIAN; + + /** perform DoF processing at native resolution */ + public boolean nativeResolution = false; + + /** + *

Number of of rings used by the foreground kernel. The number of rings affects quality + * and performance. The actual number of sample per pixel is defined + * as (ringCount * 2 - 1)^2. Here are a few commonly used values:

+ * 3 rings : 25 ( 5x 5 grid) + * 4 rings : 49 ( 7x 7 grid) + * 5 rings : 81 ( 9x 9 grid) + * 17 rings : 1089 (33x33 grid) + * + *

With a maximum circle-of-confusion of 32, it is never necessary to use more than 17 rings.

+ * + *

Usually all three settings below are set to the same value, however, it is often + * acceptable to use a lower ring count for the "fast tiles", which improves performance. + * Fast tiles are regions of the screen where every pixels have a similar + * circle-of-confusion radius.

+ * + *

A value of 0 means default, which is 5 on desktop and 3 on mobile.

+ */ + public int foregroundRingCount = 0; + + /** + * Number of of rings used by the background kernel. The number of rings affects quality + * and performance. + * @see #foregroundRingCount + */ + public int backgroundRingCount = 0; + + /** + * Number of of rings used by the fast gather kernel. The number of rings affects quality + * and performance. + * @see #foregroundRingCount + */ + public int fastGatherRingCount = 0; + + /** + * maximum circle-of-confusion in pixels for the foreground, must be in [0, 32] range. + * A value of 0 means default, which is 32 on desktop and 24 on mobile. + */ + public int maxForegroundCOC = 0; + + /** + * maximum circle-of-confusion in pixels for the background, must be in [0, 32] range. + * A value of 0 means default, which is 32 on desktop and 24 on mobile. + */ + public int maxBackgroundCOC = 0; }; /** @@ -1393,7 +1442,10 @@ public class View { */ public void setDepthOfFieldOptions(@NonNull DepthOfFieldOptions options) { mDepthOfFieldOptions = options; - nSetDepthOfFieldOptions(getNativeObject(), options.focusDistance, options.cocScale, options.maxApertureDiameter, options.enabled, options.filter.ordinal()); + nSetDepthOfFieldOptions(getNativeObject(), options.focusDistance, options.cocScale, + options.maxApertureDiameter, options.enabled, options.filter.ordinal(), + options.nativeResolution, options.foregroundRingCount, options.backgroundRingCount, + options.fastGatherRingCount, options.maxForegroundCOC, options.maxBackgroundCOC); } /** @@ -1452,7 +1504,8 @@ public class View { private static native void nSetBloomOptions(long nativeView, long dirtNativeObject, float dirtStrength, float strength, int resolution, float anamorphism, int levels, int blendMode, boolean threshold, boolean enabled, float highlight); private static native void nSetFogOptions(long nativeView, float distance, float maximumOpacity, float height, float heightFalloff, float v, float v1, float v2, float density, float inScatteringStart, float inScatteringSize, boolean fogColorFromIbl, boolean enabled); private static native void nSetBlendMode(long nativeView, int blendMode); - private static native void nSetDepthOfFieldOptions(long nativeView, float focusDistance, float cocScale, float maxApertureDiameter, boolean enabled, int filter); + private static native void nSetDepthOfFieldOptions(long nativeView, float focusDistance, float cocScale, float maxApertureDiameter, boolean enabled, int filter, + boolean nativeResolution, int foregroundRingCount, int backgroundRingCount, int fastGatherRingCount, int maxForegroundCOC, int maxBackgroundCOC); private static native void nSetVignetteOptions(long nativeView, float midPoint, float roundness, float feather, float r, float g, float b, float a, boolean enabled); private static native void nSetTemporalAntiAliasingOptions(long nativeView, float feedback, float filterWidth, boolean enabled); private static native boolean nIsShadowingEnabled(long nativeView); diff --git a/filament/CMakeLists.txt b/filament/CMakeLists.txt index 1f724ad030..cdc5cbcc05 100644 --- a/filament/CMakeLists.txt +++ b/filament/CMakeLists.txt @@ -191,6 +191,11 @@ list(APPEND SRCS ${RESGEN_SOURCE}) # Configuration # ================================================================================================== +# whether we're building for mobile -- this can affect some default quality settings +if (IS_MOBILE_TARGET) + add_definitions(-DFILAMENT_TARGET_MOBILE=1) +endif() + # Size of the DFG lookup table if (NOT DFG_LUT_SIZE) if (IS_MOBILE_TARGET) diff --git a/filament/include/filament/View.h b/filament/include/filament/View.h index 1a7706f6f3..59bee02ceb 100644 --- a/filament/include/filament/View.h +++ b/filament/include/filament/View.h @@ -196,6 +196,43 @@ public: float maxApertureDiameter = 0.01f; //!< maximum aperture diameter in meters (zero to disable rotation) bool enabled = false; //!< enable or disable depth of field effect Filter filter = Filter::MEDIAN; //!< filter to use for filling gaps in the kernel + bool nativeResolution = false; //!< perform DoF processing at native resolution + /** + * Number of of rings used by the gather kernels. The number of rings affects quality + * and performance. The actual number of sample per pixel is defined + * as (ringCount * 2 - 1)^2. Here are a few commonly used values: + * 3 rings : 25 ( 5x 5 grid) + * 4 rings : 49 ( 7x 7 grid) + * 5 rings : 81 ( 9x 9 grid) + * 17 rings : 1089 (33x33 grid) + * + * With a maximum circle-of-confusion of 32, it is never necessary to use more than 17 rings. + * + * Usually all three settings below are set to the same value, however, it is often + * acceptable to use a lower ring count for the "fast tiles", which improves performance. + * Fast tiles are regions of the screen where every pixels have a similar + * circle-of-confusion radius. + * + * A value of 0 means default, which is 5 on desktop and 3 on mobile. + * + * @{ + */ + uint8_t foregroundRingCount = 0; //!< number of kernel rings for foreground tiles + uint8_t backgroundRingCount = 0; //!< number of kernel rings for background tiles + uint8_t fastGatherRingCount = 0; //!< number of kernel rings for fast tiles + /** @}*/ + + /** + * maximum circle-of-confusion in pixels for the foreground, must be in [0, 32] range. + * A value of 0 means default, which is 32 on desktop and 24 on mobile. + */ + uint16_t maxForegroundCOC = 0; + + /** + * maximum circle-of-confusion in pixels for the background, must be in [0, 32] range. + * A value of 0 means default, which is 32 on desktop and 24 on mobile. + */ + uint16_t maxBackgroundCOC = 0; }; /** @@ -434,11 +471,11 @@ public: */ void setBlendMode(BlendMode blendMode) noexcept; - /** - * - * @return blending mode set by setBlendMode - * @see setBlendMode - */ + /** + * + * @return blending mode set by setBlendMode + * @see setBlendMode + */ BlendMode getBlendMode() const noexcept; /** diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp index 4cc34a17a8..e79cf27a9e 100644 --- a/filament/src/PostProcessManager.cpp +++ b/filament/src/PostProcessManager.cpp @@ -14,6 +14,14 @@ * limitations under the License. */ +#ifdef FILAMENT_TARGET_MOBILE +# define DOF_DEFAULT_RING_COUNT 3 +# define DOF_DEFAULT_MAX_COC 24 +#else +# define DOF_DEFAULT_RING_COUNT 5 +# define DOF_DEFAULT_MAX_COC 32 +#endif + #include "PostProcessManager.h" #include "details/Engine.h" @@ -921,7 +929,7 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, * dofResolution is used (at compile time for now) to chose between full- or quarter-resolution * for the DoF calculations. Set to [1] for full resolution or [2] for quarter-resolution. */ - const uint32_t dofResolution = 2; + const uint32_t dofResolution = dofOptions.nativeResolution ? 1u : 2u; constexpr const uint32_t maxMipLevels = 4u; // mip levels at full-resolution constexpr const uint32_t maxMipLevelsMask = (1u << maxMipLevels) - 1u; @@ -979,6 +987,9 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, mi->setParameter("color", color, { .filterMin = SamplerMinFilter::NEAREST }); mi->setParameter("depth", depth, { .filterMin = SamplerMinFilter::NEAREST }); mi->setParameter("cocParams", cocParams); + mi->setParameter("cocClamp", float2{ + -(dofOptions.maxForegroundCOC ? dofOptions.maxForegroundCOC : DOF_DEFAULT_MAX_COC), + dofOptions.maxBackgroundCOC ? dofOptions.maxBackgroundCOC : DOF_DEFAULT_MAX_COC}); mi->setParameter("uvscale", float4{ width, height, 1.0f / colorDesc.width, 1.0f / colorDesc.height }); commitAndRender(out, material, driver); @@ -1202,6 +1213,12 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, outputDesc.width / float(tileSize / dofResolution * tilesDesc.width), outputDesc.height / float(tileSize / dofResolution * tilesDesc.height) }); + mi->setParameter("ringCounts", float4{ + dofOptions.foregroundRingCount ? dofOptions.foregroundRingCount : DOF_DEFAULT_RING_COUNT, + dofOptions.backgroundRingCount ? dofOptions.backgroundRingCount : DOF_DEFAULT_RING_COUNT, + dofOptions.fastGatherRingCount ? dofOptions.fastGatherRingCount : DOF_DEFAULT_RING_COUNT, + 0.0 // unused for now + }); mi->setParameter("bokehAngle", bokehAngle); commitAndRender(out, material, driver); }); diff --git a/filament/src/materials/dof/dof.mat b/filament/src/materials/dof/dof.mat index 51568c2dbb..0068554a53 100644 --- a/filament/src/materials/dof/dof.mat +++ b/filament/src/materials/dof/dof.mat @@ -31,14 +31,19 @@ material { name : cocToPixelScale, precision: medium }, + { + type : float, + name : bokehAngle, + }, { type : float4, name : uvscale, precision: high }, { - type : float, - name : bokehAngle, + type : float4, + name : ringCounts, + precision: medium } ], outputs : [ @@ -75,20 +80,6 @@ fragment { #define DOF_DIAPHRAGM_STRAIGHT_BLADES 1 #define DOF_DIAPHRAGM DOF_DIAPHRAGM_CIRCLE -// # of sample w.r.t. ring count and density of 8 -// 3 rings : 25 ( 5^2 grid) -// 4 rings : 49 ( 7^2 grid) -// 5 rings : 81 ( 9^2 grid) -// 17 rings : 1089 (33^2 grid) -- maximum needed for a CoC of 32 - -#if defined(TARGET_MOBILE) -#define RING_COUNT_GATHER 3 -#define RING_COUNT_FAST 3 -#else -#define RING_COUNT_GATHER 4 -#define RING_COUNT_FAST 4 -#endif - // Enabled by default. Mipmaped taps look a lot better, but do cause some // aliasing issues which force us to set all sample weights to 1.0 // This is here mostly for debugging. @@ -106,6 +97,22 @@ struct NoiseState { vec2 randomDisk; }; +// # of sample w.r.t. ring count and density of 8 +// 3 rings : 25 ( 5^2 grid) +// 4 rings : 49 ( 7^2 grid) +// 5 rings : 81 ( 9^2 grid) +// 17 rings : 1089 (33^2 grid) -- maximum needed for a CoC of 32 + +float ringCountForeground() { + return materialParams.ringCounts[0]; +} +float ringCountBackground() { + return materialParams.ringCounts[1]; +} +float ringCountFast() { + return materialParams.ringCounts[2]; +} + float sampleCount(const float ringCount) { float s = (ringCount * 2.0 - 1.0); return s * s; @@ -469,7 +476,7 @@ void fastTile(inout vec4 color, inout float alpha, // The whole tile has mostly the same CoC float kernelSize = (abs(tiles.r) + abs(tiles.g)) * 0.5; - float ringCountFast = min(float(RING_COUNT_FAST), computeNeededRings(kernelSize * cocToPixelScale)); + float ringCountFast = min(ringCountFast(), computeNeededRings(kernelSize * cocToPixelScale)); float mip = getMipLevel(ringCountFast, kernelSize * cocToPixelScale); vec2 noise = vec2(0.0); @@ -510,7 +517,7 @@ void foregroundTile(inout vec4 foreground, inout float fgOpacity, // Here we know that tiles.r < 0, by definition of a foreground tile. // For a foreground tile, the kernel size is the largest CoC radius of the whole tile. float kernelSize = -tiles.r; - float ringCountGather = min(float(RING_COUNT_GATHER), computeNeededRings(kernelSize * cocToPixelScale)); + float ringCountGather = min(ringCountForeground(), computeNeededRings(kernelSize * cocToPixelScale)); float mip = getMipLevel(ringCountGather, kernelSize * cocToPixelScale); vec2 noise = vec2(0.0); @@ -563,7 +570,7 @@ void backgroundTile(inout vec4 background, inout float bgOpacity, float cocToPixelScale = materialParams.cocToPixelScale; // we select a ring cound per tile, to avoid divergence between pixels - float ringCountGather = min(float(RING_COUNT_GATHER), computeNeededRings(tiles.g * cocToPixelScale)); + float ringCountGather = min(ringCountBackground(), computeNeededRings(tiles.g * cocToPixelScale)); float centerCoc = textureLod(materialParams_coc, uv, 0.0).r; float kernelSize = abs(centerCoc); @@ -582,16 +589,9 @@ void backgroundTile(inout vec4 background, inout float bgOpacity, initBucket(prev); accumulateRing(prev, 0.0, ringCountGather, kernelSize, noise, uvCenter, cocToTexelScale, mip, true); - - // the optimizer is not able to remove this loop when it has only one iteration -#if RING_COUNT_GATHER == 3 - accumulateRing(prev, 1.0, ringCountGather, kernelSize, noise, uvCenter, cocToTexelScale, mip, false); -#else for (float i = 1.0; i < ringCountGather - 1.0 ; i += 1.0) { accumulateRing(prev, i, ringCountGather, kernelSize, noise, uvCenter, cocToTexelScale, mip, false); } -#endif - accumulateBackgroundCenter(prev, uvCenter, ringCountGather, kernelSize, noiseRadius, mip); float kernelArea = sampleWeight(kernelSize * ((ringCountGather + 0.5) / ringCountGather), mip); diff --git a/filament/src/materials/dof/dofCoc.mat b/filament/src/materials/dof/dofCoc.mat index da7a7b830b..4ff3d1d3c8 100644 --- a/filament/src/materials/dof/dofCoc.mat +++ b/filament/src/materials/dof/dofCoc.mat @@ -15,6 +15,10 @@ material { type : float2, name : cocParams }, + { + type : float2, + name : cocClamp + }, { type : float4, name : uvscale, @@ -67,7 +71,7 @@ void postProcess(inout PostProcessInputs postProcess) { float outCoc = getCOC(d, materialParams.cocParams) * 0.5; // Clamp to maximum allowable CoC radius. - outCoc = clamp(outCoc, -MAX_COC_RADIUS, MAX_COC_RADIUS); + outCoc = clamp(outCoc, materialParams.cocClamp[0], materialParams.cocClamp[1]); // If CoC is less that 0.5 full resolution pixel, we clamp to 0, this will reduce // artifacts in the "in focus" area and allow us to skip more tiles trivially. diff --git a/filament/src/materials/dof/dofDownsample.mat b/filament/src/materials/dof/dofDownsample.mat index 8b4073fd5a..7bcea00e45 100644 --- a/filament/src/materials/dof/dofDownsample.mat +++ b/filament/src/materials/dof/dofDownsample.mat @@ -15,6 +15,10 @@ material { type : float2, name : cocParams }, + { + type : float2, + name : cocClamp + }, { type : float4, name : uvscale, @@ -91,7 +95,7 @@ void postProcess(inout PostProcessInputs postProcess) { vec4 outColor = (s01 * w[0] + s11 * w[1] + s10 * w[2] + s00 * w[3]) * rcp(dot(vec4(1.0), w)); // Clamp to maximum allowable CoC radius. - outCoc = clamp(outCoc, -MAX_COC_RADIUS, MAX_COC_RADIUS); + outCoc = clamp(outCoc, materialParams.cocClamp[0], materialParams.cocClamp[1]); // If CoC is less that 0.5 full resolution pixel, we clamp to 0, this will reduce // artifacts in the "in focus" area and allow us to skip more tiles trivially. diff --git a/libs/viewer/src/Settings.cpp b/libs/viewer/src/Settings.cpp index 75d8da1b6d..61393afd1f 100644 --- a/libs/viewer/src/Settings.cpp +++ b/libs/viewer/src/Settings.cpp @@ -71,6 +71,12 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, uint8_t* return i + 1; } +static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, uint16_t* val) { + CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); + *val = strtol(jsonChunk + tokens[i].start, nullptr, 10); + return i + 1; +} + static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, uint32_t* val) { CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE); *val = strtol(jsonChunk + tokens[i].start, nullptr, 10); @@ -481,6 +487,18 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, DepthOfF i = parse(tokens, i + 1, jsonChunk, &out->enabled); } else if (0 == compare(tok, jsonChunk, "filter")) { i = parse(tokens, i + 1, jsonChunk, &out->filter); + } else if (0 == compare(tok, jsonChunk, "nativeResolution")) { + i = parse(tokens, i + 1, jsonChunk, &out->nativeResolution); + } else if (0 == compare(tok, jsonChunk, "foregroundRingCount")) { + i = parse(tokens, i + 1, jsonChunk, &out->foregroundRingCount); + } else if (0 == compare(tok, jsonChunk, "backgroundRingCount")) { + i = parse(tokens, i + 1, jsonChunk, &out->backgroundRingCount); + } else if (0 == compare(tok, jsonChunk, "fastGatherRingCount")) { + i = parse(tokens, i + 1, jsonChunk, &out->fastGatherRingCount); + } else if (0 == compare(tok, jsonChunk, "maxForegroundCOC")) { + i = parse(tokens, i + 1, jsonChunk, &out->maxForegroundCOC); + } else if (0 == compare(tok, jsonChunk, "maxBackgroundCOC")) { + i = parse(tokens, i + 1, jsonChunk, &out->maxBackgroundCOC); } else { slog.w << "Invalid dof options key: '" << STR(tok, jsonChunk) << "'" << io::endl; i = parse(tokens, i + 1); @@ -1185,7 +1203,13 @@ static std::ostream& operator<<(std::ostream& out, const DepthOfFieldOptions& in << "\"cocScale\": " << (in.cocScale) << ",\n" << "\"maxApertureDiameter\": " << (in.maxApertureDiameter) << ",\n" << "\"enabled\": " << to_string(in.enabled) << ",\n" - << "\"filter\": " << (in.filter) << "\n" + << "\"filter\": " << (in.filter) << ",\n" + << "\"nativeResolution\": " << (in.nativeResolution) << ",\n" + << "\"foregroundRingCount\": " << (in.foregroundRingCount) << ",\n" + << "\"backgroundRingCount\": " << (in.backgroundRingCount) << ",\n" + << "\"fastGatherRingCount\": " << (in.fastGatherRingCount) << ",\n" + << "\"maxForegroundCOC\": " << (in.maxForegroundCOC) << ",\n" + << "\"maxBackgroundCOC\": " << (in.maxBackgroundCOC) << "\n" << "}"; } diff --git a/libs/viewer/src/SimpleViewer.cpp b/libs/viewer/src/SimpleViewer.cpp index e0af8cf735..aadd51b8c9 100644 --- a/libs/viewer/src/SimpleViewer.cpp +++ b/libs/viewer/src/SimpleViewer.cpp @@ -729,7 +729,11 @@ void SimpleViewer::updateUserInterface() { 16.0f, 90.0f); } - bool median = mSettings.view.dof.filter == View::DepthOfFieldOptions::Filter::MEDIAN; + bool dofMedian = mSettings.view.dof.filter == View::DepthOfFieldOptions::Filter::MEDIAN; + int dofRingCount = mSettings.view.dof.fastGatherRingCount; + int dofMaxCoC = mSettings.view.dof.maxForegroundCOC; + if (!dofRingCount) dofRingCount = 5; + if (!dofMaxCoC) dofMaxCoC = 32; ImGui::SliderFloat("Aperture", &mSettings.viewer.cameraAperture, 1.0f, 32.0f); ImGui::SliderFloat("Speed (1/s)", &mSettings.viewer.cameraSpeed, 1000.0f, 1.0f); @@ -737,10 +741,19 @@ void SimpleViewer::updateUserInterface() { ImGui::Checkbox("DoF", &mSettings.view.dof.enabled); ImGui::SliderFloat("Focus distance", &mSettings.view.dof.focusDistance, 0.0f, 30.0f); ImGui::SliderFloat("Blur scale", &mSettings.view.dof.cocScale, 0.1f, 10.0f); - ImGui::Checkbox("Median Filter", &median); - mSettings.view.dof.filter = median ? - View::DepthOfFieldOptions::Filter::MEDIAN : - View::DepthOfFieldOptions::Filter::NONE; + ImGui::SliderInt("Ring count", &dofRingCount, 1, 17); + ImGui::SliderInt("Max CoC", &dofMaxCoC, 1, 32); + ImGui::Checkbox("Native Resolution", &mSettings.view.dof.nativeResolution); + ImGui::Checkbox("Median Filter", &dofMedian); + + mSettings.view.dof.filter = dofMedian ? + View::DepthOfFieldOptions::Filter::MEDIAN : + View::DepthOfFieldOptions::Filter::NONE; + mSettings.view.dof.backgroundRingCount = dofRingCount; + mSettings.view.dof.foregroundRingCount = dofRingCount; + mSettings.view.dof.fastGatherRingCount = dofRingCount; + mSettings.view.dof.maxForegroundCOC = dofMaxCoC; + mSettings.view.dof.maxBackgroundCOC = dofMaxCoC; if (ImGui::CollapsingHeader("Vignette")) { ImGui::Checkbox("Enabled##vignetteEnabled", &mSettings.view.vignette.enabled); diff --git a/web/filament-js/jsbindings.cpp b/web/filament-js/jsbindings.cpp index 5b34a6dc3a..5ea32c448d 100644 --- a/web/filament-js/jsbindings.cpp +++ b/web/filament-js/jsbindings.cpp @@ -368,7 +368,13 @@ value_object("View$DepthOfFieldOptions") .field("cocScale", &filament::View::DepthOfFieldOptions::cocScale) .field("maxApertureDiameter", &filament::View::DepthOfFieldOptions::maxApertureDiameter) .field("enabled", &filament::View::DepthOfFieldOptions::enabled) - .field("filter", &filament::View::DepthOfFieldOptions::filter); + .field("filter", &filament::View::DepthOfFieldOptions::filter) + .field("nativeResolution", &filament::View::DepthOfFieldOptions::nativeResolution) + .field("foregroundRingCount", &filament::View::DepthOfFieldOptions::foregroundRingCount) + .field("backgroundRingCount", &filament::View::DepthOfFieldOptions::backgroundRingCount) + .field("fastGatherRingCount", &filament::View::DepthOfFieldOptions::fastGatherRingCount) + .field("maxForegroundCOC", &filament::View::DepthOfFieldOptions::maxForegroundCOC) + .field("maxBackgroundCOC", &filament::View::DepthOfFieldOptions::maxBackgroundCOC); value_object("View$BloomOptions") .field("dirtStrength", &filament::View::BloomOptions::dirtStrength)