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)