From 4de1b0de2dced97df044b2590cad4dc54e0841b1 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Mon, 22 Mar 2021 16:54:08 -0700 Subject: [PATCH] DoF: add a "filter" parameter to the DoF settings Currently the only NONE and MEDIAN are available options, at some point we may add a "MAX" option which is cheaper. There is no real practical uses for this option with these only two choices, other than for debugging. --- .../filament-android/src/main/cpp/View.cpp | 9 +++++++-- .../com/google/android/filament/View.java | 13 ++++++++++-- filament/include/filament/View.h | 5 +++++ filament/src/PostProcessManager.cpp | 2 +- libs/viewer/src/Settings.cpp | 20 +++++++++++++++++++ samples/gltf_viewer.cpp | 6 ++++++ web/filament-js/filament.d.ts | 6 ++++++ web/filament-js/jsbindings.cpp | 3 ++- web/filament-js/jsenums.cpp | 4 ++++ 9 files changed, 62 insertions(+), 6 deletions(-) diff --git a/android/filament-android/src/main/cpp/View.cpp b/android/filament-android/src/main/cpp/View.cpp index 5bfe01e59d..541adb0eed 100644 --- a/android/filament-android/src/main/cpp/View.cpp +++ b/android/filament-android/src/main/cpp/View.cpp @@ -300,10 +300,15 @@ 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) { + jlong nativeView, jfloat focusDistance, jfloat cocScale, jfloat maxApertureDiameter, jboolean enabled, jint filter) { View* view = (View*) nativeView; + View::DepthOfFieldOptions::Filter eFilter{}; + if (filter == 1) { + // View::DepthOfFieldOptions::Filter::MEDIAN value is actually 2 + eFilter = View::DepthOfFieldOptions::Filter::MEDIAN; + } view->setDepthOfFieldOptions({.focusDistance = focusDistance, .cocScale = cocScale, - .maxApertureDiameter = maxApertureDiameter, .enabled = (bool)enabled}); + .maxApertureDiameter = maxApertureDiameter, .enabled = (bool)enabled, .filter = eFilter}); } 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 55398823bd..59190eb0e7 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 @@ -431,6 +431,11 @@ public class View { */ public static class DepthOfFieldOptions { + public enum Filter { + NONE, + MEDIAN + } + /** focus distance in world units */ public float focusDistance = 10.0f; @@ -451,6 +456,10 @@ public class View { /** enable or disable Depth of field effect */ public boolean enabled = false; + + /** filter to use for filling gaps in the kernel */ + @NonNull + public Filter filter = Filter.MEDIAN; }; /** @@ -1379,7 +1388,7 @@ public class View { */ public void setDepthOfFieldOptions(@NonNull DepthOfFieldOptions options) { mDepthOfFieldOptions = options; - nSetDepthOfFieldOptions(getNativeObject(), options.focusDistance, options.cocScale, options.maxApertureDiameter, options.enabled); + nSetDepthOfFieldOptions(getNativeObject(), options.focusDistance, options.cocScale, options.maxApertureDiameter, options.enabled, options.filter.ordinal()); } /** @@ -1438,7 +1447,7 @@ 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); + private static native void nSetDepthOfFieldOptions(long nativeView, float focusDistance, float cocScale, float maxApertureDiameter, boolean enabled, int filter); 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/include/filament/View.h b/filament/include/filament/View.h index 571acb51f0..dcfe6bc587 100644 --- a/filament/include/filament/View.h +++ b/filament/include/filament/View.h @@ -175,10 +175,15 @@ public: * @see Camera */ struct DepthOfFieldOptions { + enum class Filter : uint8_t { + NONE = 0, + MEDIAN = 2 + }; float focusDistance = 10.0f; //!< focus distance in world units float cocScale = 1.0f; //!< circle of confusion scale factor (amount of blur) 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 }; /** diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp index 1ac83f220c..89c93fcabb 100644 --- a/filament/src/PostProcessManager.cpp +++ b/filament/src/PostProcessManager.cpp @@ -1271,7 +1271,7 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, auto outForeground = ppDoFMedian->outForeground; auto outAlpha = ppDoFMedian->outAlpha; - if (/* DISABLES CODE */ (false)) { // TODO: make this a quality setting + if (dofOptions.filter == View::DepthOfFieldOptions::Filter::NONE) { outForeground = ppDoF->outForeground; outAlpha = ppDoF->outAlpha; } diff --git a/libs/viewer/src/Settings.cpp b/libs/viewer/src/Settings.cpp index 7a8a5e5b2a..eebcf95080 100644 --- a/libs/viewer/src/Settings.cpp +++ b/libs/viewer/src/Settings.cpp @@ -452,6 +452,15 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, FogOptio return i; } +static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, DepthOfFieldOptions::Filter* out) { + if (0 == compare(tokens[i], jsonChunk, "NONE")) { *out = DepthOfFieldOptions::Filter::NONE; } + else if (0 == compare(tokens[i], jsonChunk, "MEDIAN")) { *out = DepthOfFieldOptions::Filter::MEDIAN; } + else { + slog.w << "Invalid DepthOfFieldOptions::Filter: '" << STR(tokens[i], jsonChunk) << "'" << io::endl; + } + return i + 1; +} + static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, DepthOfFieldOptions* out) { CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); int size = tokens[i++].size; @@ -466,6 +475,8 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, DepthOfF i = parse(tokens, i + 1, jsonChunk, &out->maxApertureDiameter); } else if (0 == compare(tok, jsonChunk, "enabled")) { i = parse(tokens, i + 1, jsonChunk, &out->enabled); + } else if (0 == compare(tok, jsonChunk, "filter")) { + i = parse(tokens, i + 1, jsonChunk, &out->filter); } else { slog.w << "Invalid dof options key: '" << STR(tok, jsonChunk) << "'" << io::endl; i = parse(tokens, i + 1); @@ -886,6 +897,14 @@ static std::ostream& operator<<(std::ostream& out, CGQL in) { return out << "\"INVALID\""; } +static std::ostream& operator<<(std::ostream& out, DepthOfFieldOptions::Filter in) { + switch (in) { + case DepthOfFieldOptions::Filter::NONE: return out << "\"NONE\""; + case DepthOfFieldOptions::Filter::MEDIAN: return out << "\"MEDIAN\""; + } + return out << "\"INVALID\""; +} + static std::ostream& operator<<(std::ostream& out, ToneMapping in) { switch (in) { case ToneMapping::LINEAR: return out << "\"LINEAR\""; @@ -1083,6 +1102,7 @@ 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" << "}"; } diff --git a/samples/gltf_viewer.cpp b/samples/gltf_viewer.cpp index 04d951b584..b1afd20ab1 100644 --- a/samples/gltf_viewer.cpp +++ b/samples/gltf_viewer.cpp @@ -586,6 +586,8 @@ int main(int argc, char** argv) { if (ImGui::CollapsingHeader("Camera")) { ViewSettings& settings = app.viewer->getSettings().view; + bool median = settings.dof.filter == View::DepthOfFieldOptions::Filter::MEDIAN; + ImGui::Indent(); ImGui::SliderFloat("Focal length (mm)", &FilamentApp::get().getCameraFocalLength(), 16.0f, 90.0f); ImGui::SliderFloat("Aperture", &app.viewOptions.cameraAperture, 1.0f, 32.0f); @@ -594,6 +596,10 @@ int main(int argc, char** argv) { ImGui::Checkbox("DoF", &settings.dof.enabled); ImGui::SliderFloat("Focus distance", &settings.dof.focusDistance, 0.0f, 30.0f); ImGui::SliderFloat("Blur scale", &settings.dof.cocScale, 0.1f, 10.0f); + ImGui::Checkbox("Median Filter", &median); + settings.dof.filter = median ? + View::DepthOfFieldOptions::Filter::MEDIAN : + View::DepthOfFieldOptions::Filter::NONE; if (ImGui::CollapsingHeader("Vignette")) { ImGui::Checkbox("Enabled##vignetteEnabled", &settings.vignette.enabled); diff --git a/web/filament-js/filament.d.ts b/web/filament-js/filament.d.ts index 1484cbea93..9dd862b15d 100644 --- a/web/filament-js/filament.d.ts +++ b/web/filament-js/filament.d.ts @@ -106,6 +106,7 @@ export interface View$DepthOfFieldOptions { cocScale?: number; maxApertureDiameter?: number; enabled?: boolean; + filter?: View$DepthOfFieldOptions$Filter; } export interface View$BloomOptions { @@ -1000,6 +1001,11 @@ export enum View$AmbientOcclusion { SSAO, } +export enum View$DepthOfFieldOptions$Filter { + NONE, + MEDIAN = 2, +} + export enum View$BloomOptions$BlendMode { ADD, INTERPOLATE, diff --git a/web/filament-js/jsbindings.cpp b/web/filament-js/jsbindings.cpp index 8a809e57b3..556a6f1198 100644 --- a/web/filament-js/jsbindings.cpp +++ b/web/filament-js/jsbindings.cpp @@ -367,7 +367,8 @@ value_object("View$DepthOfFieldOptions") .field("focusDistance", &filament::View::DepthOfFieldOptions::focusDistance) .field("cocScale", &filament::View::DepthOfFieldOptions::cocScale) .field("maxApertureDiameter", &filament::View::DepthOfFieldOptions::maxApertureDiameter) - .field("enabled", &filament::View::DepthOfFieldOptions::enabled); + .field("enabled", &filament::View::DepthOfFieldOptions::enabled) + .field("filter", &filament::View::DepthOfFieldOptions::filter); value_object("View$BloomOptions") .field("dirtStrength", &filament::View::BloomOptions::dirtStrength) diff --git a/web/filament-js/jsenums.cpp b/web/filament-js/jsenums.cpp index 7b0f9849da..9e63c23213 100644 --- a/web/filament-js/jsenums.cpp +++ b/web/filament-js/jsenums.cpp @@ -136,6 +136,10 @@ enum_("View$AntiAliasing") .value("NONE", View::AntiAliasing::NONE) .value("FXAA", View::AntiAliasing::FXAA); +enum_("View$DepthOfFieldOptions$Filter") + .value("NONE", View::DepthOfFieldOptions::Filter::NONE) + .value("MEDIAN", View::DepthOfFieldOptions::Filter::MEDIAN); + enum_("Camera$Fov") .value("VERTICAL", Camera::Fov::VERTICAL) .value("HORIZONTAL", Camera::Fov::HORIZONTAL);