From 1b36f82c1e6658f21300cf1d5dda614b15f97b29 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Fri, 10 Apr 2020 15:54:14 -0700 Subject: [PATCH] API BREAKAGE: this change aims to fix multi-view support (#2376) * API BREAKAGE: this change aims to fix multi-view support What has changed: - View doesn't have a notion of clear color anymore - View doesn't have a notion of discard flags anymore - The clear color and color-buffer discard/clear flags are moved to Renderer - Skybox can now be set to a constant color - View have a blend-mode What does is all mean: "Clearing" (i.e.) setting its background is now handled by Skybox, by setting a constant color to the Skybox. This should take care of drawing views side by side. When a view needs to be drawn on top of another, it's BlendMode needs to be set to TRANSLUCENT and of course and, generally, it wither won't have a skybox, or will have one that sets some translucent pixels. As an optimization, a View with BlendMode::OPAQUE will have its background cleared with the color specified in Renderer. If the SwapChain already has some content, it's now possible to set the Renderer to not discard the content, together with TRANSLUCENT views, it's possible to draw on top of that content. It is NOT possible to share depth/stencil buffers between views. Fixes: #2369, #2372, #2364 * Address reviewers comments. Note: WebGL is still broken with this PR --- .../src/main/cpp/Renderer.cpp | 10 ++ .../filament-android/src/main/cpp/SkyBox.cpp | 16 +++ .../filament-android/src/main/cpp/View.cpp | 36 ++----- .../com/google/android/filament/Renderer.java | 51 +++++++++ .../com/google/android/filament/Skybox.java | 51 +++++++++ .../com/google/android/filament/View.java | 102 ++++++++---------- .../android/filament/hellocam/MainActivity.kt | 2 +- .../filament/hellotriangle/MainActivity.kt | 5 +- .../android/filament/ibl/MainActivity.kt | 5 - .../android/filament/litcube/MainActivity.kt | 5 +- .../filament/material_builder/MainActivity.kt | 5 - .../filament/multiview/MainActivity.kt | 28 ++--- .../filament/streamtest/MainActivity.kt | 2 +- .../filament/textureview/MainActivity.kt | 5 +- .../android/filament/textured/MainActivity.kt | 5 - .../transparentrendering/MainActivity.kt | 8 +- filament/include/filament/Renderer.h | 31 ++++++ filament/include/filament/Scene.h | 2 +- filament/include/filament/Skybox.h | 14 +++ filament/include/filament/View.h | 52 +++------ filament/src/Renderer.cpp | 100 +++++++++-------- filament/src/Scene.cpp | 8 +- filament/src/Skybox.cpp | 37 +++++-- filament/src/View.cpp | 40 ++----- filament/src/details/Renderer.h | 7 ++ filament/src/details/Scene.h | 5 +- filament/src/details/Skybox.h | 8 +- filament/src/details/View.h | 45 ++------ filament/src/fg/FrameGraphHandle.h | 3 +- .../src/fg/fg/RenderTargetResourceEntry.cpp | 4 +- filament/src/materials/skybox.mat | 21 +++- filament/test/filament_rendering_test.cpp | 11 +- .../hello-triangle/FilamentView.mm | 2 +- .../transparent-rendering/FilamentView.mm | 2 +- libs/filamentapp/src/FilamentApp.cpp | 11 +- samples/animation.cpp | 6 +- samples/depthtesting.cpp | 7 +- samples/frame_generator.cpp | 20 ++-- samples/gltf_viewer.cpp | 6 +- samples/heightfield.cpp | 6 +- samples/hellotriangle.cpp | 6 +- samples/point_sprites.cpp | 7 +- samples/shadowtest.cpp | 6 +- samples/strobecolor.cpp | 11 +- samples/texturedquad.cpp | 7 +- samples/viewtest.cpp | 6 +- web/filament-js/jsbindings.cpp | 1 - 47 files changed, 495 insertions(+), 333 deletions(-) diff --git a/android/filament-android/src/main/cpp/Renderer.cpp b/android/filament-android/src/main/cpp/Renderer.cpp index 405fddaf1c..b140b50a5d 100644 --- a/android/filament-android/src/main/cpp/Renderer.cpp +++ b/android/filament-android/src/main/cpp/Renderer.cpp @@ -163,3 +163,13 @@ Java_com_google_android_filament_Renderer_nSetFrameRateOptions(JNIEnv*, jclass, .history = (uint8_t)history, .interval = (uint8_t)interval }); } + +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_Renderer_nSetClearOptions(JNIEnv *, jclass , + jlong nativeRenderer, jfloat r, jfloat g, jfloat b, jfloat a, + jboolean clear, jboolean discard) { + Renderer *renderer = (Renderer *) nativeRenderer; + renderer->setClearOptions({ .clearColor = {r, g, b, a}, + .clear = (bool) clear, + .discard = (bool) discard}); +} diff --git a/android/filament-android/src/main/cpp/SkyBox.cpp b/android/filament-android/src/main/cpp/SkyBox.cpp index 6b31d27a32..7fbd81ce32 100644 --- a/android/filament-android/src/main/cpp/SkyBox.cpp +++ b/android/filament-android/src/main/cpp/SkyBox.cpp @@ -18,6 +18,8 @@ #include +#include + using namespace filament; extern "C" JNIEXPORT jlong JNICALL @@ -54,6 +56,13 @@ Java_com_google_android_filament_Skybox_nBuilderIntensity(JNIEnv *env, jclass cl builder->intensity(intensity); } +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_Skybox_nBuilderColor(JNIEnv *, jclass, + jlong nativeSkyBoxBuilder, jfloat r, jfloat g, jfloat b, jfloat a) { + Skybox::Builder *builder = (Skybox::Builder *) nativeSkyBoxBuilder; + builder->color({r, g, b, a}); +} + extern "C" JNIEXPORT jlong JNICALL Java_com_google_android_filament_Skybox_nBuilderBuild(JNIEnv *env, jclass type, jlong nativeSkyBoxBuilder, jlong nativeEngine) { @@ -82,3 +91,10 @@ Java_com_google_android_filament_Skybox_nGetIntensity(JNIEnv *env, jclass clazz, Skybox *skybox = (Skybox *) nativeSkybox; return static_cast(skybox->getIntensity()); } + +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_Skybox_nSetColor(JNIEnv *, jclass, + jlong nativeSkybox, jfloat r, jfloat g, jfloat b, jfloat a) { + Skybox *skybox = (Skybox *) nativeSkybox; + skybox->setColor({r, g, b, a}); +} diff --git a/android/filament-android/src/main/cpp/View.cpp b/android/filament-android/src/main/cpp/View.cpp index 174433e9b3..d67c934622 100644 --- a/android/filament-android/src/main/cpp/View.cpp +++ b/android/filament-android/src/main/cpp/View.cpp @@ -50,32 +50,6 @@ Java_com_google_android_filament_View_nSetViewport(JNIEnv*, jclass, view->setViewport({left, bottom, (uint32_t) width, (uint32_t) height}); } -extern "C" JNIEXPORT void JNICALL -Java_com_google_android_filament_View_nSetClearColor(JNIEnv*, jclass, jlong nativeView, - jfloat linearR, jfloat linearG, jfloat linearB, jfloat linearA) { - View* view = (View*) nativeView; - view->setClearColor({linearR, linearG, linearB, linearA}); -} - -extern "C" JNIEXPORT void JNICALL -Java_com_google_android_filament_View_nGetClearColor(JNIEnv* env, jclass, jlong nativeView, jfloatArray out_) { - View* view = (View*) nativeView; - jfloat* out = env->GetFloatArrayElements(out_, NULL); - auto linearColor = view->getClearColor(); - out[0] = linearColor[0]; - out[1] = linearColor[1]; - out[2] = linearColor[2]; - out[3] = linearColor[3]; - env->ReleaseFloatArrayElements(out_, out, 0); -} - -extern "C" JNIEXPORT void JNICALL -Java_com_google_android_filament_View_nSetClearTargets(JNIEnv*, jclass, - jlong nativeView, jboolean color, jboolean depth, jboolean stencil) { - View* view = (View*) nativeView; - view->setClearTargets(color, depth, stencil); -} - extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_View_nSetVisibleLayers(JNIEnv*, jclass, jlong nativeView, jint select, jint value) { View* view = (View*) nativeView; @@ -90,9 +64,9 @@ Java_com_google_android_filament_View_nSetShadowsEnabled(JNIEnv*, jclass, jlong extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_View_nSetRenderTarget(JNIEnv*, jclass, - jlong nativeView, jlong nativeTarget, jint flags) { + jlong nativeView, jlong nativeTarget) { View* view = (View*) nativeView; - view->setRenderTarget((RenderTarget*) nativeTarget, (View::TargetBufferFlags) flags); + view->setRenderTarget((RenderTarget*) nativeTarget); } extern "C" JNIEXPORT void JNICALL @@ -272,3 +246,9 @@ Java_com_google_android_filament_View_nSetFogOptions(JNIEnv *, jclass , jlong na }; view->setFogOptions(options); } + +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_View_nSetBlendMode(JNIEnv *, jclass , jlong nativeView, jint blendMode) { + View* view = (View*) nativeView; + view->setBlendMode((View::BlendMode)blendMode); +} diff --git a/android/filament-android/src/main/java/com/google/android/filament/Renderer.java b/android/filament-android/src/main/java/com/google/android/filament/Renderer.java index 59c93c52c9..a009691baf 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/Renderer.java +++ b/android/filament-android/src/main/java/com/google/android/filament/Renderer.java @@ -46,6 +46,7 @@ public class Renderer { private long mNativeObject; private DisplayInfo mDisplayInfo; private FrameRateOptions mFrameRateOptions; + private ClearOptions mClearOptions; /** * Information about the display this renderer is associated to @@ -114,6 +115,30 @@ public class Renderer { public int history = 9; } + /** + * ClearOptions are used at the beginning of a frame to clear or retain the SwapChain content. + */ + public static class ClearOptions { + /** + * Color to use to clear the SwapChain + */ + @NonNull + public float[] clearColor = { 0.0f, 0.0f, 0.0f, 0.0f }; + + /** + * Whether the SwapChain should be cleared using the clearColor. Use this if translucent + * View will be drawn, for instance. + */ + public boolean clear = false; + + /** + * Whether the SwapChain content should be discarded. clear implies discard. Set this + * to false (along with clear to false as well) if the SwapChain already has content that + * needs to be preserved + */ + public boolean discard = true; + }; + /** * Indicates that the dstSwapChain passed into {@link #copyFrame} should be * committed after the frame has been copied. @@ -188,6 +213,30 @@ public class Renderer { return mFrameRateOptions; } + /** + * Set ClearOptions which are used at the beginning of a frame to clear or retain the + * SwapChain content. + */ + public void setClearOptions(@NonNull ClearOptions options) { + mClearOptions = options; + nSetClearOptions(getNativeObject(), + options.clearColor[0], options.clearColor[1], options.clearColor[2], options.clearColor[3], + options.clear, options.discard); + } + + /** + * Returns the ClearOptions object set in {@link #setClearOptions} or a new instance + * otherwise. + * @return a ClearOptions instance + */ + @NonNull + public ClearOptions getClearOptions() { + if (mClearOptions == null) { + mClearOptions = new ClearOptions(); + } + return mClearOptions; + } + /** * Gets the {@link Engine} that created this Renderer. * @@ -604,4 +653,6 @@ public class Renderer { float refreshRate, long presentationDeadlineNanos, long vsyncOffsetNanos); private static native void nSetFrameRateOptions(long nativeRenderer, float interval, float headRoomRatio, float scaleRate, int history); + private static native void nSetClearOptions(long nativeRenderer, + float r, float g, float b, float a, boolean clear, boolean discard); } diff --git a/android/filament-android/src/main/java/com/google/android/filament/Skybox.java b/android/filament-android/src/main/java/com/google/android/filament/Skybox.java index d2753869f0..57b07a5dbf 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/Skybox.java +++ b/android/filament-android/src/main/java/com/google/android/filament/Skybox.java @@ -18,6 +18,9 @@ package com.google.android.filament; import androidx.annotation.IntRange; import androidx.annotation.NonNull; +import androidx.annotation.Size; + +import static com.google.android.filament.Colors.LinearColor; import com.google.android.filament.proguard.UsedByReflection; @@ -126,6 +129,33 @@ public class Skybox { return this; } + /** + * Sets the Skybox to a constant color. Default is opaque black. + * + * Ignored if an environment is set. + * + * @return This Builder, for chaining calls. + */ + @NonNull + public Builder color(@LinearColor float r, @LinearColor float g, @LinearColor float b, float a) { + nBuilderColor(mNativeBuilder, r, g, b, a); + return this; + } + + /** + * Sets the Skybox to a constant color. Default is opaque black. + * + * Ignored if an environment is set. + * + * @param color an array of 4 floats + * @return This Builder, for chaining calls. + */ + @NonNull + public Builder color(@NonNull @Size(min = 4) float[] color) { + nBuilderColor(mNativeBuilder, color[0], color[1], color[2], color[3]); + return this; + } + /** * Creates a Skybox object * @@ -159,6 +189,25 @@ public class Skybox { } } + /** + * Mutates the Skybox's constant color. + * + * Ignored if an environment is set. + */ + public void setColor(@LinearColor float r, @LinearColor float g, @LinearColor float b, float a) { + nSetColor(getNativeObject(), r, g, b, a); + } + + /** + * Mutates the Skybox's constant color. + * Ignored if an environment is set. + * + * @param color an array of 4 floats + */ + public void setColor(@NonNull @Size(min = 4) float[] color) { + nSetColor(getNativeObject(), color[0], color[1], color[2], color[3]); + } + /** * Sets bits in a visibility mask. By default, this is 0x1. *

This provides a simple mechanism for hiding or showing this Skybox in a @@ -204,8 +253,10 @@ public class Skybox { private static native void nBuilderEnvironment(long nativeSkyboxBuilder, long nativeTexture); private static native void nBuilderShowSun(long nativeSkyboxBuilder, boolean show); private static native void nBuilderIntensity(long nativeSkyboxBuilder, float intensity); + private static native void nBuilderColor(long nativeSkyboxBuilder, float r, float g, float b, float a); private static native long nBuilderBuild(long nativeSkyboxBuilder, long nativeEngine); private static native void nSetLayerMask(long nativeSkybox, int select, int value); private static native int nGetLayerMask(long nativeSkybox); private static native float nGetIntensity(long nativeSkybox); + private static native void nSetColor(long nativeSkybox, float r, float g, float b, float a); } 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 fe7d2f127d..be1f7ca734 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 @@ -68,6 +68,7 @@ public class View { private BloomOptions mBloomOptions; private FogOptions mFogOptions; private RenderTarget mRenderTarget; + private BlendMode mBlendMode; /** * Generic Quality Level @@ -79,6 +80,11 @@ public class View { ULTRA } + public enum BlendMode { + OPAQUE, + TRANSLUCENT + } + /** * Dynamic resolution can be used to either reach a desired target frame rate by lowering the * resolution of a View, or to increase the quality when the rendering is faster @@ -556,39 +562,23 @@ public class View { } /** - * Sets the color used to clear the Viewport when rendering this View. + * Sets the blending mode used to draw the view into the SwapChain. * - *

This is ignored if a {@link Skybox} is present or if clearing has been disabled - * via {@link #setClearTargets}. Defaults to black.

- * - * @see #getClearColor + * @param blendMode either {@link BlendMode#OPAQUE} or {@link BlendMode#TRANSLUCENT} + * @see #getBlendMode */ - public void setClearColor( - @LinearColor float r, @LinearColor float g, @LinearColor float b, float a) { - nSetClearColor(getNativeObject(), r, g, b, a); + public void setBlendMode(BlendMode blendMode) { + mBlendMode = blendMode; + nSetBlendMode(getNativeObject(), blendMode.ordinal()); } /** - * Returns the View clear color in a provided 4-tuple. * - * @return A reference to the passed-in array. - * - * @see #setClearColor + * @return blending mode set by setBlendMode + * @see #setBlendMode */ - @NonNull @Size(min = 4) - public float[] getClearColor(@NonNull @Size(min = 4) float[] out) { - out = Asserts.assertFloat4(out); - nGetClearColor(getNativeObject(), out); - return out; - } - - /** - * Sets which targets to clear (default: true, true, false) - * - * @see #setClearColor - */ - public void setClearTargets(boolean color, boolean depth, boolean stencil) { - nSetClearTargets(getNativeObject(), color, depth, stencil); + public BlendMode getBlendMode() { + return mBlendMode; } /** @@ -630,33 +620,12 @@ public class View { * By default, the view's associated render target is null, which corresponds to the * SwapChain associated with the engine. *

- *

- * This method discards the content of all the buffers in the render target. See - * {@link #setRenderTarget(RenderTarget, EnumSet)} if you need more precise control. - *

* * @param target render target associated with view, or null for the swap chain */ public void setRenderTarget(@Nullable RenderTarget target) { - setRenderTarget(target, TargetBufferFlags.ALL); - } - - /** - * Specifies an offscreen render target to render into. - * - *

- * By default, the view's associated render target is null, which corresponds to the - * SwapChain associated with the engine. - *

- * - * @param target render target associated with view, or null for the swap chain - * @param flags buffers that need to be discarded before rendering. - */ - public void setRenderTarget(@Nullable RenderTarget target, - @NonNull EnumSet flags) { mRenderTarget = target; - nSetRenderTarget(getNativeObject(), target != null ? target.getNativeObject() : 0, - TargetBufferFlags.flags(flags)); + nSetRenderTarget(getNativeObject(), target != null ? target.getNativeObject() : 0); } /** @@ -954,6 +923,7 @@ public class View { * Sets bloom options. * * @param options Options for bloom. + * @see #getBloomOptions */ public void setBloomOptions(@NonNull BloomOptions options) { mBloomOptions = options; @@ -963,10 +933,25 @@ public class View { options.threshold, options.enabled); } + /** + * Gets the bloom options + * @see #setBloomOptions + * + * @return bloom options currently set. + */ + @NonNull + public BloomOptions getBloomOptions() { + if (mBloomOptions == null) { + mBloomOptions = new BloomOptions(); + } + return mBloomOptions; + } + /** * Sets fog options. * * @param options Options for fog. + * @see #getFogOptions */ public void setFogOptions(@NonNull FogOptions options) { mFogOptions = options; @@ -978,18 +963,20 @@ public class View { } /** - * Gets the bloom options + * Gets the fog options * - * @return bloom options currently set. + * @return fog options currently set. + * @see #setFogOptions */ @NonNull - public BloomOptions getBloomOptions() { - if (mBloomOptions == null) { - mBloomOptions = new BloomOptions(); + public FogOptions getFogOptions() { + if (mFogOptions == null) { + mFogOptions = new FogOptions(); } - return mBloomOptions; + return mFogOptions; } + public long getNativeObject() { if (mNativeObject == 0) { throw new IllegalStateException("Calling method on destroyed View"); @@ -1005,12 +992,9 @@ public class View { private static native void nSetScene(long nativeView, long nativeScene); private static native void nSetCamera(long nativeView, long nativeCamera); private static native void nSetViewport(long nativeView, int left, int bottom, int width, int height); - private static native void nSetClearColor(long nativeView, float r, float g, float b, float a); - private static native void nGetClearColor(long nativeView, float[] out); - private static native void nSetClearTargets(long nativeView, boolean color, boolean depth, boolean stencil); private static native void nSetVisibleLayers(long nativeView, int select, int value); private static native void nSetShadowsEnabled(long nativeView, boolean enabled); - private static native void nSetRenderTarget(long nativeView, long nativeRenderTarget, int flags); + private static native void nSetRenderTarget(long nativeView, long nativeRenderTarget); private static native void nSetSampleCount(long nativeView, int count); private static native int nGetSampleCount(long nativeView); private static native void nSetAntiAliasing(long nativeView, int type); @@ -1031,5 +1015,5 @@ public class View { private static native void nSetAmbientOcclusionOptions(long nativeView, float radius, float bias, float power, float resolution, float intensity, int quality); 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); 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); } diff --git a/android/samples/sample-hello-camera/src/main/java/com/google/android/filament/hellocam/MainActivity.kt b/android/samples/sample-hello-camera/src/main/java/com/google/android/filament/hellocam/MainActivity.kt index e36130d9b4..9cdc483313 100644 --- a/android/samples/sample-hello-camera/src/main/java/com/google/android/filament/hellocam/MainActivity.kt +++ b/android/samples/sample-hello-camera/src/main/java/com/google/android/filament/hellocam/MainActivity.kt @@ -113,7 +113,7 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba } private fun setupView() { - view.setClearColor(0.035f, 0.035f, 0.035f, 1.0f) + scene.skybox = Skybox.Builder().color(0.035f, 0.035f, 0.035f, 1.0f).build(engine) view.camera = camera view.scene = scene } diff --git a/android/samples/sample-hello-triangle/src/main/java/com/google/android/filament/hellotriangle/MainActivity.kt b/android/samples/sample-hello-triangle/src/main/java/com/google/android/filament/hellotriangle/MainActivity.kt index 4365c6c605..637671fc03 100644 --- a/android/samples/sample-hello-triangle/src/main/java/com/google/android/filament/hellotriangle/MainActivity.kt +++ b/android/samples/sample-hello-triangle/src/main/java/com/google/android/filament/hellotriangle/MainActivity.kt @@ -117,10 +117,7 @@ class MainActivity : Activity() { } private fun setupView() { - // Clear the background to middle-grey - // Setting up a clear color is useful for debugging but usually - // unnecessary when using a skybox - view.setClearColor(0.035f, 0.035f, 0.035f, 1.0f) + scene.skybox = Skybox.Builder().color(0.035f, 0.035f, 0.035f, 1.0f).build(engine) // NOTE: Try to disable post-processing (tone-mapping, etc.) to see the difference // view.isPostProcessingEnabled = false diff --git a/android/samples/sample-image-based-lighting/src/main/java/com/google/android/filament/ibl/MainActivity.kt b/android/samples/sample-image-based-lighting/src/main/java/com/google/android/filament/ibl/MainActivity.kt index ba475b4a86..ff47f85df5 100644 --- a/android/samples/sample-image-based-lighting/src/main/java/com/google/android/filament/ibl/MainActivity.kt +++ b/android/samples/sample-image-based-lighting/src/main/java/com/google/android/filament/ibl/MainActivity.kt @@ -117,11 +117,6 @@ class MainActivity : Activity() { } private fun setupView() { - // Clear the background to middle-grey - // Setting up a clear color is useful for debugging but usually - // unnecessary when using a skybox - view.setClearColor(0.035f, 0.035f, 0.035f, 1.0f) - view.ambientOcclusion = View.AmbientOcclusion.SSAO // NOTE: Try to disable post-processing (tone-mapping, etc.) to see the difference diff --git a/android/samples/sample-lit-cube/src/main/java/com/google/android/filament/litcube/MainActivity.kt b/android/samples/sample-lit-cube/src/main/java/com/google/android/filament/litcube/MainActivity.kt index bb7952c84a..80d4664f86 100644 --- a/android/samples/sample-lit-cube/src/main/java/com/google/android/filament/litcube/MainActivity.kt +++ b/android/samples/sample-lit-cube/src/main/java/com/google/android/filament/litcube/MainActivity.kt @@ -118,10 +118,7 @@ class MainActivity : Activity() { } private fun setupView() { - // Clear the background to middle-grey - // Setting up a clear color is useful for debugging but usually - // unnecessary when using a skybox - view.setClearColor(0.035f, 0.035f, 0.035f, 1.0f) + scene.skybox = Skybox.Builder().color(0.035f, 0.035f, 0.035f, 1.0f).build(engine) // NOTE: Try to disable post-processing (tone-mapping, etc.) to see the difference // view.isPostProcessingEnabled = false diff --git a/android/samples/sample-material-builder/src/main/java/com/google/android/filament/material_builder/MainActivity.kt b/android/samples/sample-material-builder/src/main/java/com/google/android/filament/material_builder/MainActivity.kt index bb53f2953e..aeaed65353 100644 --- a/android/samples/sample-material-builder/src/main/java/com/google/android/filament/material_builder/MainActivity.kt +++ b/android/samples/sample-material-builder/src/main/java/com/google/android/filament/material_builder/MainActivity.kt @@ -116,11 +116,6 @@ class MainActivity : Activity() { } private fun setupView() { - // Clear the background to middle-grey - // Setting up a clear color is useful for debugging but usually - // unnecessary when using a skybox - view.setClearColor(0.035f, 0.035f, 0.035f, 1.0f) - // NOTE: Try to disable post-processing (tone-mapping, etc.) to see the difference // view.isPostProcessingEnabled = false diff --git a/android/samples/sample-multi-view/src/main/java/com/google/android/filament/multiview/MainActivity.kt b/android/samples/sample-multi-view/src/main/java/com/google/android/filament/multiview/MainActivity.kt index a7fd2d678a..a970b08065 100644 --- a/android/samples/sample-multi-view/src/main/java/com/google/android/filament/multiview/MainActivity.kt +++ b/android/samples/sample-multi-view/src/main/java/com/google/android/filament/multiview/MainActivity.kt @@ -65,6 +65,8 @@ class MainActivity : Activity() { private lateinit var view1: View private lateinit var view2: View private lateinit var view3: View + // We need skybox to set the background color + private lateinit var skybox: Skybox // Should be pretty obvious :) private lateinit var camera: Camera @@ -123,24 +125,13 @@ class MainActivity : Activity() { view2.setName("view2"); view3.setName("view3"); + skybox = Skybox.Builder().build(engine); + scene.skybox = skybox + camera = engine.createCamera() } private fun setupViews() { - // To use multi-view properly with mobile GPUs, we need to make sure to tell - // Filament to not discard buffers after the first view we render - view1.setRenderTarget(null, View.TargetBufferFlags.NONE) - view2.setRenderTarget(null, View.TargetBufferFlags.NONE) - view3.setRenderTarget(null, View.TargetBufferFlags.NONE) - - // Clears are not restricted by the scissor so we want to disable clear targets - // except for the first view we render - view1.setClearTargets(false, false, false) - view2.setClearTargets(false, false, false) - view3.setClearTargets(false, false, false) - - view0.setClearColor(0.035f, 0.035f, 0.035f, 1.0f) - view0.camera = camera view1.camera = camera view2.camera = camera @@ -382,6 +373,7 @@ class MainActivity : Activity() { engine.destroyView(view1) engine.destroyView(view2) engine.destroyView(view3) + engine.destroySkybox(skybox) engine.destroyScene(scene) engine.destroyCamera(camera) @@ -406,10 +398,18 @@ class MainActivity : Activity() { // If beginFrame() returns false you should skip the frame // This means you are sending frames too quickly to the GPU if (renderer.beginFrame(swapChain!!, frameTimeNanos)) { + skybox.setColor(0.035f, 0.035f, 0.035f, 1.0f); renderer.render(view0) + + skybox.setColor(1.0f, 0.0f, 0.0f, 1.0f); renderer.render(view1) + + skybox.setColor(0.0f, 1.0f, 0.0f, 1.0f); renderer.render(view2) + + skybox.setColor(0.0f, 0.0f, 1.0f, 1.0f); renderer.render(view3) + renderer.endFrame() } } diff --git a/android/samples/sample-stream-test/src/main/java/com/google/android/filament/streamtest/MainActivity.kt b/android/samples/sample-stream-test/src/main/java/com/google/android/filament/streamtest/MainActivity.kt index 7fdd05f45e..33545b7fb7 100644 --- a/android/samples/sample-stream-test/src/main/java/com/google/android/filament/streamtest/MainActivity.kt +++ b/android/samples/sample-stream-test/src/main/java/com/google/android/filament/streamtest/MainActivity.kt @@ -125,7 +125,7 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba } private fun setupView() { - view.setClearColor(0.035f, 0.035f, 0.035f, 1.0f) + scene.skybox = Skybox.Builder().color(0.035f, 0.035f, 0.035f, 1.0f).build(engine) view.camera = camera view.scene = scene } diff --git a/android/samples/sample-texture-view/src/main/java/com/google/android/filament/textureview/MainActivity.kt b/android/samples/sample-texture-view/src/main/java/com/google/android/filament/textureview/MainActivity.kt index 435b134530..55db366043 100644 --- a/android/samples/sample-texture-view/src/main/java/com/google/android/filament/textureview/MainActivity.kt +++ b/android/samples/sample-texture-view/src/main/java/com/google/android/filament/textureview/MainActivity.kt @@ -117,10 +117,7 @@ class MainActivity : Activity() { } private fun setupView() { - // Clear the background to middle-grey - // Setting up a clear color is useful for debugging but usually - // unnecessary when using a skybox - view.setClearColor(0.035f, 0.035f, 0.035f, 1.0f) + scene.skybox = Skybox.Builder().color(0.035f, 0.035f, 0.035f, 1.0f).build(engine) // NOTE: Try to disable post-processing (tone-mapping, etc.) to see the difference // view.isPostProcessingEnabled = false diff --git a/android/samples/sample-textured-object/src/main/java/com/google/android/filament/textured/MainActivity.kt b/android/samples/sample-textured-object/src/main/java/com/google/android/filament/textured/MainActivity.kt index 1dcca6a75b..5cd67e350f 100644 --- a/android/samples/sample-textured-object/src/main/java/com/google/android/filament/textured/MainActivity.kt +++ b/android/samples/sample-textured-object/src/main/java/com/google/android/filament/textured/MainActivity.kt @@ -121,11 +121,6 @@ class MainActivity : Activity() { } private fun setupView() { - // Clear the background to middle-grey - // Setting up a clear color is useful for debugging but usually - // unnecessary when using a skybox - view.setClearColor(0.035f, 0.035f, 0.035f, 1.0f) - // NOTE: Try to disable post-processing (tone-mapping, etc.) to see the difference // view.isPostProcessingEnabled = false diff --git a/android/samples/sample-transparent-view/src/main/java/com/google/android/filament/transparentrendering/MainActivity.kt b/android/samples/sample-transparent-view/src/main/java/com/google/android/filament/transparentrendering/MainActivity.kt index 8ff038ae13..8ab5da530d 100644 --- a/android/samples/sample-transparent-view/src/main/java/com/google/android/filament/transparentrendering/MainActivity.kt +++ b/android/samples/sample-transparent-view/src/main/java/com/google/android/filament/transparentrendering/MainActivity.kt @@ -137,12 +137,14 @@ class MainActivity : Activity() { scene = engine.createScene() view = engine.createView() camera = engine.createCamera() + + // clear the swapchain with transparent pixels + val options = renderer.clearOptions + options.clear = true + renderer.clearOptions = options } private fun setupView() { - // Make sure to clear to a fully transparent color - view.setClearColor(0.0f, 0.0f, 0.0f, 0.0f) - // Tell the view which camera we want to use view.camera = camera diff --git a/filament/include/filament/Renderer.h b/filament/include/filament/Renderer.h index fd405d4ef6..7a6d2bee1e 100644 --- a/filament/include/filament/Renderer.h +++ b/filament/include/filament/Renderer.h @@ -69,6 +69,10 @@ class PixelBufferDescriptor; class UTILS_PUBLIC Renderer : public FilamentAPI { public: + /** + * Use DisplayInfo to set important Display properties. This is used to achieve correct + * frame pacing and dynamic resolution scaling. + */ struct DisplayInfo { // refresh-rate of the display in Hz. set to 0 for offscreen or turn off frame-pacing. float refreshRate = 60.0f; @@ -109,6 +113,25 @@ public: uint8_t interval = 1; //!< desired frame interval in unit of 1.0 / DisplayInfo::refreshRate }; + /** + * ClearOptions are used at the beginning of a frame to clear or retain the SwapChain content. + */ + struct ClearOptions { + /** Color to use to clear the SwapChain */ + math::float4 clearColor = {}; + /** + * Whether the SwapChain should be cleared using the clearColor. Use this if translucent + * View will be drawn, for instance. + */ + bool clear = false; + /** + * Whether the SwapChain content should be discarded. clear implies discard. Set this + * to false (along with clear to false as well) if the SwapChain already has content that + * needs to be preserved + */ + bool discard = true; + }; + /** * Information about the display this Renderer is associated to. This information is needed * to accurately compute dynamic-resolution scaling and for frame-pacing. @@ -124,6 +147,14 @@ public: */ void setFrameRateOptions(FrameRateOptions const& options) noexcept; + /** + * Set ClearOptions which are used at the beginning of a frame to clear or retain the + * SwapChain content. + * + * @param options + */ + void setClearOptions(const ClearOptions& options); + /** * Get the Engine that created this Renderer. * diff --git a/filament/include/filament/Scene.h b/filament/include/filament/Scene.h index 6dca2229fc..2ce7d0bce8 100644 --- a/filament/include/filament/Scene.h +++ b/filament/include/filament/Scene.h @@ -72,7 +72,7 @@ public: * * @param skybox The Skybox to use to fill untouched pixels, or nullptr to unset the Skybox. */ - void setSkybox(Skybox const* skybox) noexcept; + void setSkybox(Skybox* skybox) noexcept; /** * Set the IndirectLight to use when rendering the Scene. diff --git a/filament/include/filament/Skybox.h b/filament/include/filament/Skybox.h index d453e6779a..6081f8f2d3 100644 --- a/filament/include/filament/Skybox.h +++ b/filament/include/filament/Skybox.h @@ -24,6 +24,7 @@ #include #include +#include namespace filament { @@ -121,6 +122,17 @@ public: */ Builder& intensity(float envIntensity) noexcept; + /** + * Sets the skybox to a constant color. Default is opaque black. + * + * Ignored if an environment is set. + * + * @param color + * + * @return This Builder, for chaining calls. + */ + Builder& color(math::float4 color) noexcept; + /** * Creates the Skybox object and returns a pointer to it. * @@ -134,6 +146,8 @@ public: friend class details::FSkybox; }; + void setColor(math::float4 color) noexcept; + /** * Sets bits in a visibility mask. By default, this is 0x1. * diff --git a/filament/include/filament/View.h b/filament/include/filament/View.h index 3e881714e7..b6c7ffc9d9 100644 --- a/filament/include/filament/View.h +++ b/filament/include/filament/View.h @@ -62,13 +62,18 @@ class UTILS_PUBLIC View : public FilamentAPI { public: using TargetBufferFlags = backend::TargetBufferFlags; - enum class QualityLevel : int8_t { + enum class QualityLevel : uint8_t { LOW, MEDIUM, HIGH, ULTRA }; + enum class BlendMode : uint8_t { + OPAQUE, + TRANSLUCENT + }; + /** * Dynamic resolution can be used to either reach a desired target frame rate * by lowering the resolution of a View, or to increase the quality when the @@ -345,37 +350,19 @@ public: Viewport const& getViewport() const noexcept; /** - * Sets the color used to clear the Viewport when rendering this View. - * Defaults to black. + * Sets the blending mode used to draw the view into the SwapChain. * - * @param clearColor The color to use to clear the Viewport. - * @see setClearTargets + * @param blendMode either BlendMode::OPAQUE or BlendMode::TRANSLUCENT + * @see getBlendMode */ - void setClearColor(LinearColorA const& clearColor) noexcept; + void setBlendMode(BlendMode blendMode) noexcept; - /** - * Returns the View clear color. - * @return A constant reference to the View's clear color. - */ - LinearColorA const& getClearColor() const noexcept; - - /** - * Sets which targets to clear (default: true, true, false) - * @param color Clear the color buffer. The color buffer is cleared with the color set in - * setClearColor(). - * @param depth Clear the depth buffer. The depth buffer is cleared with an implementation - * defined value representing the farthest depth. - * - * @note - * Generally the depth clear value is 1.0, but you shouldn't rely on this - * because filament may use "inverted depth" in some situations. - * - * - * @param stencil Clear the stencil buffer. The stencil buffer is cleared with 0. - * - * @see setClearColor - */ - void setClearTargets(bool color, bool depth, bool stencil) noexcept; + /** + * + * @return blending mode set by setBlendMode + * @see setBlendMode + */ + BlendMode getBlendMode() const noexcept; /** * Sets which layers are visible. @@ -414,13 +401,8 @@ public: * SwapChain associated with the engine. * * @param renderTarget Render target associated with view, or nullptr for the swap chain. - * @param discard Buffers that need to be discarded before rendering. */ - void setRenderTarget(RenderTarget* renderTarget, - TargetBufferFlags discard = TargetBufferFlags::ALL) noexcept; - - //! @deprecated Please use the other overload and pass nullptr for the renderTarget. - void setRenderTarget(TargetBufferFlags discard = TargetBufferFlags::ALL) noexcept; + void setRenderTarget(RenderTarget* renderTarget) noexcept; /** * Gets the offscreen render target associated with this view. diff --git a/filament/src/Renderer.cpp b/filament/src/Renderer.cpp index 2a729b65b6..fc7b028571 100644 --- a/filament/src/Renderer.cpp +++ b/filament/src/Renderer.cpp @@ -258,44 +258,48 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { FrameGraph fg(engine.getResourceAllocator()); - const TargetBufferFlags discardedFlags = view.getDiscardedTargetBuffers(); + const TargetBufferFlags discardedFlags = mDiscardedFlags; + const TargetBufferFlags clearFlags = mClearFlags; + const float4 clearColor = mClearOptions.clearColor; - TargetBufferFlags clearFlags = (view.getClearFlags() & TargetBufferFlags::COLOR); - - // if the depth-buffer is discarded, then we clear it -- the corollary is that if the user - // doesn't ask for the depth buffer to be discarded, then we keep it. This is needed if - // the user wants to keep the depth buffer between two calls to render(). This of course - // only works when post-processing is disabled. - if (any(discardedFlags & TargetBufferFlags::DEPTH)) { - clearFlags |= TargetBufferFlags::DEPTH; - } - - const float4 clearColor = view.getClearColor(); - - // Figure out if we need to blend this view into the framebuffer. Maybe this should be - // explicit, but since we don't have an API right now, we use heuristics: - // - we are keeping the color buffer before rendering, and - // - we are not clearing or clearing with alpha - // FIXME: make this an explicit API - const bool blending = !(discardedFlags & TargetBufferFlags::COLOR) - && (!(clearFlags & TargetBufferFlags::COLOR) || clearColor.a < 1.0); - - // If the swapchain is transparent or if we blend into it, we need to allocate our intermediate - // buffers with an alpha channel. - // FIXME: this doesn't work when the target is a user provided rendertarget - const bool translucent = mSwapChain->isTransparent() || blending; - - const TextureFormat hdrFormat = getHdrFormat(view, translucent); + // Renderer's ClearOptions apply once at the beginning of the frame (not for each View), + // however, it's implemented as part of executing a render pass on the current render target, + // and that happens for each View. So we need to disable clearing after the 1st View has + // been processed. + mDiscardedFlags &= ~TargetBufferFlags::COLOR; + mClearFlags &= ~TargetBufferFlags::COLOR; const Handle viewRenderTarget = getRenderTarget(view); FrameGraphRenderTargetHandle fgViewRenderTarget = fg.import( "viewRenderTarget", { - .viewport = DEBUG_DYNAMIC_SCALING ? svp : vp, .clearFlags = clearFlags }, { + .viewport = DEBUG_DYNAMIC_SCALING ? svp : vp, + .clearColor = clearColor, + .clearFlags = clearFlags + }, { .target = viewRenderTarget, .params = { .flags = { .discardStart = discardedFlags }, }}); + + const bool blending = view.getBlendMode() == View::BlendMode::TRANSLUCENT; + // If the swapchain is transparent or if we blend into it, we need to allocate our intermediate + // buffers with an alpha channel. + // FIXME: this doesn't work when the target is a user provided rendertarget + const bool translucent = mSwapChain->isTransparent() || blending; + const TextureFormat hdrFormat = getHdrFormat(view, translucent); + + const ColorPassConfig config { + .vp = vp, + .svp = svp, + .scale = scale, + .hdrFormat = hdrFormat, + .msaa = msaa, + .clearFlags = clearFlags, + .clearColor = clearColor, + .hasContactShadows = scene.hasContactShadows() + }; + /* * Depth + Color passes */ @@ -338,17 +342,6 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { pass.appendCommands(RenderPass::COLOR); pass.sortCommands(); - const ColorPassConfig config { - .vp = vp, - .svp = svp, - .scale = scale, - .hdrFormat = hdrFormat, - .msaa = msaa, - .clearFlags = clearFlags, - .clearColor = clearColor, - .hasContactShadows = scene.hasContactShadows() - }; - // We use a framegraph pass to wait for froxelization to finish (so it can be done // in parallel with .compile() fg.addTrivialSideEffectPass("Prepare Color Passes", [=, &js, &view](DriverApi& driver) { @@ -394,7 +387,8 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { if (UTILS_LIKELY(!blending && upscalingQuality == View::QualityLevel::LOW)) { input = ppm.opaqueBlit(fg, input, { .format = ldrFormat }); } else { - input = ppm.blendBlit(fg, true, upscalingQuality, input, { .format = ldrFormat }); + input = ppm.blendBlit(fg, true, upscalingQuality, input, + { .format = ldrFormat }); } } } @@ -414,7 +408,8 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { if (UTILS_LIKELY(!blending && upscalingQuality == View::QualityLevel::LOW)) { input = ppm.opaqueBlit(fg, input, { .format = ldrFormat }); } else { - input = ppm.blendBlit(fg, true, upscalingQuality, input, { .format = ldrFormat }); + input = ppm.blendBlit(fg, true, upscalingQuality, input, + { .format = ldrFormat }); } } @@ -588,10 +583,8 @@ FrameGraphId FRenderer::colorPass(FrameGraph& fg, const char* } if (!data.color.isValid()) { - clearColorFlags = TargetBufferFlags::COLOR; - if (!(config.clearFlags & TargetBufferFlags::COLOR)) { - // the View doesn't ask for a clear, but we're creating a new color - // intermediate buffer, so it must be cleared with transparent pixels. + if (!mClearOptions.clear && !view.isSkyboxVisible()) { + clearColorFlags = TargetBufferFlags::COLOR; data.clearColor = {}; } data.color = builder.createTexture("Color Buffer", colorBufferDesc); @@ -780,6 +773,19 @@ bool FRenderer::beginFrame(FSwapChain* swapChain, uint64_t vsyncSteadyClockTimeN float l = float(time.count() - h); mShaderUserTime = { h, l, 0, 0 }; + + // We always discard and clear the depth+stencil buffers -- we don't allow sharing these + // across views (clear implies discard) + + mDiscardedFlags = ((mClearOptions.discard || mClearOptions.clear) ? + TargetBufferFlags::COLOR : TargetBufferFlags::NONE) + | TargetBufferFlags::DEPTH_AND_STENCIL; + + mClearFlags = (mClearOptions.clear ? + TargetBufferFlags::COLOR : TargetBufferFlags::NONE) + | TargetBufferFlags::DEPTH_AND_STENCIL; + + // ask the engine to do what it needs to (e.g. updates light buffer, materials...) engine.prepare(); @@ -934,4 +940,8 @@ void Renderer::setFrameRateOptions(FrameRateOptions const& options) noexcept { upcast(this)->setFrameRateOptions(options); } +void Renderer::setClearOptions(const ClearOptions& options) { + upcast(this)->setClearOptions(options); +} + } // namespace filament diff --git a/filament/src/Scene.cpp b/filament/src/Scene.cpp index e0a8ba4d76..17e96707bd 100644 --- a/filament/src/Scene.cpp +++ b/filament/src/Scene.cpp @@ -230,6 +230,10 @@ void FScene::updateUBOs(utils::Range visibleRenderables, backend::Hand mHasContactShadows = hasContactShadows; mRenderableViewUbh = renderableUbh; driver.loadUniformBuffer(renderableUbh, { buffer, size }); + + if (mSkybox) { + mSkybox->commit(driver); + } } void FScene::terminate(FEngine& engine) { @@ -388,7 +392,7 @@ bool FScene::hasEntity(Entity entity) const noexcept { return mEntities.find(entity) != mEntities.end(); } -void FScene::setSkybox(FSkybox const* skybox) noexcept { +void FScene::setSkybox(FSkybox* skybox) noexcept { std::swap(mSkybox, skybox); if (skybox) { remove(skybox->getEntity()); @@ -417,7 +421,7 @@ bool FScene::hasContactShadows() const noexcept { using namespace details; -void Scene::setSkybox(Skybox const* skybox) noexcept { +void Scene::setSkybox(Skybox* skybox) noexcept { upcast(this)->setSkybox(upcast(skybox)); } diff --git a/filament/src/Skybox.cpp b/filament/src/Skybox.cpp index 6d8112eb32..31fc578d98 100644 --- a/filament/src/Skybox.cpp +++ b/filament/src/Skybox.cpp @@ -31,6 +31,8 @@ #include #include +#include + #include "generated/resources/materials.h" @@ -41,6 +43,7 @@ using namespace details; struct Skybox::BuilderDetails { Texture* mEnvironmentMap = nullptr; + float4 mColor{0, 0, 0, 1}; float mIntensity = FIndirectLight::DEFAULT_INTENSITY; bool mShowSun = false; }; @@ -64,6 +67,11 @@ Skybox::Builder& Skybox::Builder::intensity(float envIntensity) noexcept { return *this; } +Skybox::Builder& Skybox::Builder::color(math::float4 color) noexcept { + mImpl->mColor = color; + return *this; +} + Skybox::Builder& Skybox::Builder::showSun(bool show) noexcept { mImpl->mShowSun = show; return *this; @@ -73,11 +81,8 @@ Skybox* Skybox::Builder::build(Engine& engine) { FEngine::assertValid(engine, __PRETTY_FUNCTION__); FTexture* cubemap = upcast(mImpl->mEnvironmentMap); - if (!ASSERT_PRECONDITION_NON_FATAL(cubemap, "environment texture not set")) { - return nullptr; - } - - if (!ASSERT_PRECONDITION_NON_FATAL(cubemap->isCubemap(), "environment maps must be a cubemap")) { + if (!ASSERT_PRECONDITION_NON_FATAL(!cubemap || cubemap->isCubemap(), + "environment maps must be a cubemap")) { return nullptr; } @@ -97,8 +102,13 @@ FSkybox::FSkybox(FEngine& engine, const Builder& builder) noexcept mSkyboxMaterialInstance = material->createInstance(); TextureSampler sampler(TextureSampler::MagFilter::LINEAR, TextureSampler::WrapMode::REPEAT); - static_cast(mSkyboxMaterialInstance)->setParameter("skybox", mSkyboxTexture, sampler); - static_cast(mSkyboxMaterialInstance)->setParameter("showSun", builder->mShowSun); + auto pInstance = static_cast(mSkyboxMaterialInstance); + if (mSkyboxTexture != nullptr) { + pInstance->setParameter("skybox", mSkyboxTexture, sampler); + } + pInstance->setParameter("showSun", builder->mShowSun); + pInstance->setParameter("constantColor", mSkyboxTexture == nullptr); + pInstance->setParameter("color", builder->mColor); mSkybox = engine.getEntityManager().create(); @@ -139,6 +149,14 @@ void FSkybox::setLayerMask(uint8_t select, uint8_t values) noexcept { mLayerMask = (mLayerMask & ~select) | (values & select); } +void FSkybox::setColor(math::float4 color) noexcept { + mSkyboxMaterialInstance->setParameter("color", color); +} + +void FSkybox::commit(backend::DriverApi& driver) noexcept { + mSkyboxMaterialInstance->commit(driver); +} + } // namespace details // ------------------------------------------------------------------------------------------------ @@ -159,4 +177,9 @@ float Skybox::getIntensity() const noexcept { return upcast(this)->getIntensity(); } +void Skybox::setColor(math::float4 color) noexcept { + upcast(this)->setColor(color); + +} + } // namespace filament diff --git a/filament/src/View.cpp b/filament/src/View.cpp index ebc049fe9e..1a9966827a 100644 --- a/filament/src/View.cpp +++ b/filament/src/View.cpp @@ -42,6 +42,7 @@ #include #include +#include using namespace filament::math; @@ -199,16 +200,6 @@ float2 FView::updateScale(FrameInfo const& info) noexcept { return mScale; } -void FView::setClearColor(float4 const& clearColor) noexcept { - mClearColor = clearColor; -} - -void FView::setClearTargets(bool color, bool depth, bool stencil) noexcept { - mClearTargetColor = color; - mClearTargetDepth = depth; - mClearTargetStencil = stencil; -} - void FView::setVisibleLayers(uint8_t select, uint8_t values) noexcept { mVisibleLayers = (mVisibleLayers & ~select) | (values & select); } @@ -854,19 +845,6 @@ filament::Viewport const& View::getViewport() const noexcept { return upcast(this)->getViewport(); } - -void View::setClearColor(float4 const& clearColor) noexcept { - upcast(this)->setClearColor(clearColor); -} - -float4 const& View::getClearColor() const noexcept { - return upcast(this)->getClearColor(); -} - -void View::setClearTargets(bool color, bool depth, bool stencil) noexcept { - return upcast(this)->setClearTargets(color, depth, stencil); -} - void View::setFrustumCullingEnabled(bool culling) noexcept { upcast(this)->setFrustumCullingEnabled(culling); } @@ -899,12 +877,8 @@ void View::setShadowsEnabled(bool enabled) noexcept { upcast(this)->setShadowsEnabled(enabled); } -void View::setRenderTarget(RenderTarget* renderTarget, TargetBufferFlags discard) noexcept { - upcast(this)->setRenderTarget(upcast(renderTarget), discard); -} - -void View::setRenderTarget(TargetBufferFlags discard) noexcept { - upcast(this)->setRenderTarget(discard); +void View::setRenderTarget(RenderTarget* renderTarget) noexcept { + upcast(this)->setRenderTarget(upcast(renderTarget)); } RenderTarget* View::getRenderTarget() const noexcept { @@ -1007,5 +981,13 @@ View::BloomOptions View::getBloomOptions() const noexcept { return upcast(this)->getBloomOptions(); } +void View::setBlendMode(BlendMode blendMode) noexcept { + upcast(this)->setBlendMode(blendMode); +} + +View::BlendMode View::getBlendMode() const noexcept { + return upcast(this)->getBlendMode(); +} + } // namespace filament diff --git a/filament/src/details/Renderer.h b/filament/src/details/Renderer.h index d80f8d82cf..c4a3524dfd 100644 --- a/filament/src/details/Renderer.h +++ b/filament/src/details/Renderer.h @@ -115,6 +115,10 @@ public: frameRateOptions.headRoomRatio = std::max(frameRateOptions.headRoomRatio, 0.0f); } + void setClearOptions(const ClearOptions& options) { + mClearOptions = options; + } + private: friend class Renderer; using Command = RenderPass::Command; @@ -180,6 +184,9 @@ private: math::float4 mShaderUserTime{}; DisplayInfo mDisplayInfo; FrameRateOptions mFrameRateOptions; + ClearOptions mClearOptions; + backend::TargetBufferFlags mDiscardedFlags; + backend::TargetBufferFlags mClearFlags; // per-frame arena for this Renderer LinearAllocatorArena& mPerRenderPassArena; diff --git a/filament/src/details/Scene.h b/filament/src/details/Scene.h index f7d516fa91..d036582158 100644 --- a/filament/src/details/Scene.h +++ b/filament/src/details/Scene.h @@ -55,8 +55,9 @@ public: * User Public API */ - void setSkybox(FSkybox const* skybox) noexcept; + void setSkybox(FSkybox* skybox) noexcept; FSkybox const* getSkybox() const noexcept { return mSkybox; } + FSkybox* getSkybox() noexcept { return mSkybox; } void setIndirectLight(FIndirectLight const* ibl) noexcept { mIndirectLight = ibl; } FIndirectLight const* getIndirectLight() const noexcept { return mIndirectLight; } @@ -204,7 +205,7 @@ private: const CameraInfo& camera, const math::float4* spheres, size_t count) noexcept; FEngine& mEngine; - FSkybox const* mSkybox = nullptr; + FSkybox* mSkybox = nullptr; FIndirectLight const* mIndirectLight = nullptr; /* diff --git a/filament/src/details/Skybox.h b/filament/src/details/Skybox.h index ae02e7695d..06f2a1330a 100644 --- a/filament/src/details/Skybox.h +++ b/filament/src/details/Skybox.h @@ -18,6 +18,8 @@ #include +#include + #include #include @@ -44,11 +46,15 @@ public: utils::Entity getEntity() const noexcept { return mSkybox; } void setLayerMask(uint8_t select, uint8_t values) noexcept; - uint8_t getLayerMask() const noexcept { return mLayerMask; } float getIntensity() const noexcept { return mIntensity; } + void setColor(math::float4 color) noexcept; + + // commits UBOs + void commit(backend::DriverApi& driver) noexcept; + private: // we don't own these FTexture const* mSkyboxTexture = nullptr; diff --git a/filament/src/details/View.h b/filament/src/details/View.h index 5d565ca48b..beb2a06eb5 100644 --- a/filament/src/details/View.h +++ b/filament/src/details/View.h @@ -119,21 +119,9 @@ public: return mViewport; } - void setClearColor(LinearColorA const& clearColor) noexcept; - LinearColorA const& getClearColor() const noexcept { - return mClearColor; - } - - void setClearTargets(bool color, bool depth, bool stencil) noexcept; bool getClearTargetColor() const noexcept { // don't clear the color buffer if we have a skybox - return mClearTargetColor && !isSkyboxVisible(); - } - bool getClearTargetDepth() const noexcept { - return mClearTargetDepth; - } - bool getClearTargetStencil() const noexcept { - return mClearTargetStencil; + return !isSkyboxVisible(); } bool isSkyboxVisible() const noexcept; @@ -188,13 +176,8 @@ public: return &mDirectionalShadowMap.getDebugCamera(); } - void setRenderTarget(FRenderTarget* renderTarget, TargetBufferFlags discard) noexcept { + void setRenderTarget(FRenderTarget* renderTarget) noexcept { mRenderTarget = renderTarget; - mDiscardedTargetBuffers = discard; - } - - void setRenderTarget(TargetBufferFlags discard) noexcept { - mDiscardedTargetBuffers = discard; } FRenderTarget* getRenderTarget() const noexcept { @@ -233,8 +216,6 @@ public: return mDithering; } - TargetBufferFlags getDiscardedTargetBuffers() const noexcept { return mDiscardedTargetBuffers; } - bool hasPostProcessPass() const noexcept { return mHasPostProcessPass; } @@ -302,6 +283,14 @@ public: return mBloomOptions; } + void setBlendMode(BlendMode blendMode) noexcept { + mBlendMode = blendMode; + } + + BlendMode getBlendMode() const noexcept { + return mBlendMode; + } + Range const& getVisibleRenderables() const noexcept { return mVisibleRenderables; } @@ -314,14 +303,6 @@ public: return mSpotLightShadowCasters; } - TargetBufferFlags getClearFlags() const noexcept { - TargetBufferFlags clearFlags = {}; - if (getClearTargetColor()) clearFlags |= TargetBufferFlags::COLOR; - if (getClearTargetDepth()) clearFlags |= TargetBufferFlags::DEPTH; - if (getClearTargetStencil()) clearFlags |= TargetBufferFlags::STENCIL; - return clearFlags; - } - FCamera const& getCameraUser() const noexcept { return *mCullingCamera; } FCamera& getCameraUser() noexcept { return *mCullingCamera; } void setCameraUser(FCamera* camera) noexcept { setCullingCamera(camera); } @@ -380,14 +361,9 @@ private: mutable Froxelizer mFroxelizer; Viewport mViewport; - LinearColorA mClearColor{}; bool mCulling = true; bool mFrontFaceWindingInverted = false; - bool mClearTargetColor = true; - bool mClearTargetDepth = true; - bool mClearTargetStencil = false; - TargetBufferFlags mDiscardedTargetBuffers = TargetBufferFlags::ALL; FRenderTarget* mRenderTarget = nullptr; uint8_t mVisibleLayers = 0x1; @@ -401,6 +377,7 @@ private: AmbientOcclusionOptions mAmbientOcclusionOptions{}; BloomOptions mBloomOptions; FogOptions mFogOptions; + BlendMode mBlendMode = BlendMode::OPAQUE; DynamicResolutionOptions mDynamicResolution; math::float2 mScale = 1.0f; diff --git a/filament/src/fg/FrameGraphHandle.h b/filament/src/fg/FrameGraphHandle.h index 88c12b16d2..8c44ef4c6f 100644 --- a/filament/src/fg/FrameGraphHandle.h +++ b/filament/src/fg/FrameGraphHandle.h @@ -166,8 +166,9 @@ struct FrameGraphRenderTarget { struct Descriptor { Attachments attachments; Viewport viewport; + math::float4 clearColor{}; uint8_t samples = 0; // # of samples (0 = unset, default) - backend::TargetBufferFlags clearFlags = {}; + backend::TargetBufferFlags clearFlags{}; }; backend::Handle target; diff --git a/filament/src/fg/fg/RenderTargetResourceEntry.cpp b/filament/src/fg/fg/RenderTargetResourceEntry.cpp index 73e97eb57f..7651db3910 100644 --- a/filament/src/fg/fg/RenderTargetResourceEntry.cpp +++ b/filament/src/fg/fg/RenderTargetResourceEntry.cpp @@ -112,12 +112,12 @@ void RenderTargetResourceEntry::resolve(FrameGraph& fg) noexcept { resource.params.viewport.width = width; resource.params.viewport.height = height; } - resource.params.flags.clear = descriptor.clearFlags; } else { // this can happen with imported targets resource.params.viewport = descriptor.viewport; - resource.params.flags.clear = descriptor.clearFlags; } + resource.params.clearColor = descriptor.clearColor; + resource.params.flags.clear = descriptor.clearFlags; } void RenderTargetResourceEntry::update(FrameGraph& fg, PassNode const& pass) noexcept { diff --git a/filament/src/materials/skybox.mat b/filament/src/materials/skybox.mat index f44f024fa3..28277ed35d 100644 --- a/filament/src/materials/skybox.mat +++ b/filament/src/materials/skybox.mat @@ -5,9 +5,17 @@ material { type : bool, name : showSun }, + { + type : bool, + name : constantColor + }, { type : samplerCubemap, name : skybox + }, + { + type : float4, + name : color } ], variables : [ @@ -23,8 +31,13 @@ material { fragment { void material(inout MaterialInputs material) { prepareMaterial(material); - vec3 sky = texture(materialParams_skybox, variable_eyeDirection.xyz).rgb; - sky *= frameUniforms.iblLuminance; + vec4 sky; + if (materialParams.constantColor) { + sky = materialParams.color; + } else { + sky = vec4(texture(materialParams_skybox, variable_eyeDirection.xyz).rgb, 1.0); + sky.rgb *= frameUniforms.iblLuminance; + } if (materialParams.showSun && frameUniforms.sun.w >= 0.0f) { vec3 direction = normalize(variable_eyeDirection.xyz); // Assume the sun is a sphere @@ -33,9 +46,9 @@ fragment { float cosAngle = dot(direction, frameUniforms.lightDirection); float x = (cosAngle - frameUniforms.sun.x) * frameUniforms.sun.z; float gradient = pow(1.0 - saturate(x), frameUniforms.sun.w); - sky = sky + gradient * sun; + sky.rgb = sky.rgb + gradient * sun; } - material.baseColor = vec4(sky, 1.0); + material.baseColor = sky; } } diff --git a/filament/test/filament_rendering_test.cpp b/filament/test/filament_rendering_test.cpp index 645e628ef4..a7c8e90a84 100644 --- a/filament/test/filament_rendering_test.cpp +++ b/filament/test/filament_rendering_test.cpp @@ -18,6 +18,8 @@ #include #include +#include +#include #include #include @@ -32,6 +34,7 @@ protected: SwapChain* mSurface = nullptr; Renderer* mRenderer = nullptr; View* mView = nullptr; + Skybox* mSkybox = nullptr; Scene* mScene = nullptr; Camera* mCamera = nullptr; @@ -49,12 +52,16 @@ protected: mView->setViewport({0, 0, 16, 16}); mView->setScene(mScene); mView->setCamera(mCamera); + + mSkybox = Skybox::Builder().build(*mEngine); + mScene->setSkybox(mSkybox); } void TearDown() override { mEngine->destroy(mCamera); mEngine->destroy(mScene); mEngine->destroy(mView); + mEngine->destroy(mSkybox); mEngine->destroy(mRenderer); mEngine->destroy(mSurface); Engine::destroy(&mEngine); @@ -91,7 +98,7 @@ private: }; TEST_F(RenderingTest, ClearRed) { - mView->setClearColor(LinearColorA{1, 0, 0, 1}); + mSkybox->setColor(LinearColorA{1, 0, 0, 1}); mView->setToneMapping(View::ToneMapping::LINEAR); mView->setDithering(View::Dithering::NONE); runTest([this](uint8_t const* rgba, uint32_t width, uint32_t height) { @@ -103,7 +110,7 @@ TEST_F(RenderingTest, ClearRed) { } TEST_F(RenderingTest, ClearGreen) { - mView->setClearColor(LinearColorA{0, 1, 0, 1}); + mSkybox->setColor(LinearColorA{0, 1, 0, 1}); mView->setToneMapping(View::ToneMapping::LINEAR); mView->setDithering(View::Dithering::NONE); runTest([this](uint8_t const* rgba, uint32_t width, uint32_t height) { diff --git a/ios/samples/hello-triangle/hello-triangle/FilamentView.mm b/ios/samples/hello-triangle/hello-triangle/FilamentView.mm index 0759f8e209..dd222fa145 100644 --- a/ios/samples/hello-triangle/hello-triangle/FilamentView.mm +++ b/ios/samples/hello-triangle/hello-triangle/FilamentView.mm @@ -151,9 +151,9 @@ static constexpr uint8_t BAKED_COLOR_PACKAGE[] = { renderer = engine->createRenderer(); scene = engine->createScene(); camera = engine->createCamera(); + renderer->setClearOptions({.clearColor={0.1, 0.125, 0.25, 1.0}, .clear = true}); filaView = engine->createView(); - filaView->setClearColor({0.1, 0.125, 0.25, 1.0}); filaView->setPostProcessingEnabled(false); app.vb = VertexBuffer::Builder() diff --git a/ios/samples/transparent-rendering/transparent-rendering/FilamentView.mm b/ios/samples/transparent-rendering/transparent-rendering/FilamentView.mm index 60483e81d4..35d485796c 100644 --- a/ios/samples/transparent-rendering/transparent-rendering/FilamentView.mm +++ b/ios/samples/transparent-rendering/transparent-rendering/FilamentView.mm @@ -164,7 +164,7 @@ static constexpr uint8_t BAKED_COLOR_PACKAGE[] = { filaView = engine->createView(); // Set a transparent clear color. - filaView->setClearColor({0.0f, 0.0f, 0.0f, 0.0f}); + renderer->setClearOptions({.clear = true}); filaView->setPostProcessingEnabled(false); diff --git a/libs/filamentapp/src/FilamentApp.cpp b/libs/filamentapp/src/FilamentApp.cpp index 46688ed72d..a9fb0aa272 100644 --- a/libs/filamentapp/src/FilamentApp.cpp +++ b/libs/filamentapp/src/FilamentApp.cpp @@ -102,8 +102,7 @@ void FilamentApp::run(const Config& config, SetupCallback setupCallback, window->mMainView->getView()->setVisibleLayers(0x4, 0x4); - window->mUiView->getView()->setClearTargets(false, false, false); - window->mUiView->getView()->setRenderTarget(View::TargetBufferFlags::DEPTH_AND_STENCIL); + window->mUiView->getView()->setBlendMode(View::BlendMode::TRANSLUCENT); window->mUiView->getView()->setPostProcessingEnabled(false); window->mUiView->getView()->setShadowsEnabled(false); @@ -128,16 +127,9 @@ void FilamentApp::run(const Config& config, SetupCallback setupCallback, window->mOrthoView->getView()->setVisibleLayers(0x6, 0x6); // only preserve the color buffer for additional views; depth and stencil can be discarded. - window->mDepthView->getView()->setRenderTarget(View::TargetBufferFlags::DEPTH_AND_STENCIL); - window->mGodView->getView()->setRenderTarget(View::TargetBufferFlags::DEPTH_AND_STENCIL); - window->mOrthoView->getView()->setRenderTarget(View::TargetBufferFlags::DEPTH_AND_STENCIL); - window->mDepthView->getView()->setShadowsEnabled(false); window->mGodView->getView()->setShadowsEnabled(false); window->mOrthoView->getView()->setShadowsEnabled(false); - - // the depthview doesn't draw the background (ibl), so we must clear it - window->mDepthView->getView()->setClearColor({0, 0, 0, 1}); } loadDirt(config); @@ -726,7 +718,6 @@ void FilamentApp::Window::configureCamerasForWindow() { FilamentApp::CView::CView(Renderer& renderer, std::string name) : engine(*renderer.getEngine()), mName(name) { view = engine.createView(); - view->setClearColor(LinearColorA{ 0 }); view->setName(name.c_str()); } diff --git a/samples/animation.cpp b/samples/animation.cpp index c68a057912..4af6806ee7 100644 --- a/samples/animation.cpp +++ b/samples/animation.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ struct App { IndexBuffer* ib; Material* mat; Camera* cam; + Skybox* skybox; Entity renderable; }; @@ -66,7 +68,8 @@ int main(int argc, char** argv) { App app; auto setup = [&app](Engine* engine, View* view, Scene* scene) { - view->setClearColor({0.1, 0.125, 0.25, 1.0}); + app.skybox = Skybox::Builder().color({0.1, 0.125, 0.25, 1.0}).build(*engine); + scene->setSkybox(app.skybox); view->setPostProcessingEnabled(false); app.vb = VertexBuffer::Builder() .vertexCount(3).bufferCount(1) @@ -88,6 +91,7 @@ int main(int argc, char** argv) { }; auto cleanup = [&app](Engine* engine, View*, Scene*) { + engine->destroy(app.skybox); engine->destroy(app.renderable); engine->destroy(app.mat); engine->destroy(app.vb); diff --git a/samples/depthtesting.cpp b/samples/depthtesting.cpp index e07734582f..cf501c2176 100644 --- a/samples/depthtesting.cpp +++ b/samples/depthtesting.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ struct App { IndexBuffer* ib; Material* mat; Camera* cam; + Skybox* skybox; Entity whiteTriangle; Entity colorTriangle; }; @@ -67,9 +69,11 @@ int main(int argc, char** argv) { App app; auto setup = [&app](Engine* engine, View* view, Scene* scene) { + app.skybox = Skybox::Builder().color({0.1, 0.125, 0.25, 1.0}).build(*engine); + scene->setSkybox(app.skybox); + app.cam = engine->createCamera(); view->setCamera(app.cam); - view->setClearColor({0.1, 0.125, 0.25, 1.0}); view->setPostProcessingEnabled(false); app.vb = VertexBuffer::Builder() .vertexCount(3) @@ -115,6 +119,7 @@ int main(int argc, char** argv) { }; auto cleanup = [&app](Engine* engine, View*, Scene*) { + engine->destroy(app.skybox); engine->destroy(app.whiteTriangle); engine->destroy(app.colorTriangle); engine->destroy(app.mat); diff --git a/samples/frame_generator.cpp b/samples/frame_generator.cpp index 3fe94f1092..8a8765e9d3 100644 --- a/samples/frame_generator.cpp +++ b/samples/frame_generator.cpp @@ -76,6 +76,7 @@ static Path g_materialPath; static Path g_paramsPath; static bool g_lightOn = false; static bool g_skyboxOn = true; +static Skybox* g_skybox = nullptr; static int g_materialVariantCount = 1; static int g_currentFrame = 0; static std::atomic_int g_savedFrames(0); @@ -228,6 +229,10 @@ static void cleanup(Engine* engine, View*, Scene*) { engine->destroy(material.second); } + if (g_skybox) { + engine->destroy(g_skybox); + } + engine->destroy(g_materialInstance); engine->destroy(g_material); @@ -329,14 +334,15 @@ static void setup(Engine* engine, View* view, Scene* scene) { if (!g_skyboxOn) { auto ibl = FilamentApp::get().getIBL(); if (ibl) ibl->getSkybox()->setLayerMask(0xff, 0x00); + } else { + g_skybox = Skybox::Builder().color({ + ((g_clearColor >> 16) & 0xFF) / 255.0f, + ((g_clearColor >> 8) & 0xFF) / 255.0f, + ((g_clearColor ) & 0xFF) / 255.0f, + 1.0f + }).build(*engine); + scene->setSkybox(g_skybox); } - - view->setClearColor(Color::toLinear({ - ((g_clearColor >> 16) & 0xFF) / 255.0f, - ((g_clearColor >> 8) & 0xFF) / 255.0f, - ((g_clearColor ) & 0xFF) / 255.0f, - 1.0f - })); } template diff --git a/samples/gltf_viewer.cpp b/samples/gltf_viewer.cpp index 35b1b73fc4..a117a43829 100644 --- a/samples/gltf_viewer.cpp +++ b/samples/gltf_viewer.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -443,8 +444,9 @@ int main(int argc, char** argv) { if (ibl) { ibl->getSkybox()->setLayerMask(0xff, app.viewOptions.skyboxEnabled ? 0xff : 0x00); } - view->setClearColor( - LinearColorA{ inverseTonemapSRGB(app.viewOptions.backgroundColor), 1.0f }); + renderer->setClearOptions({ + .clearColor = { inverseTonemapSRGB(app.viewOptions.backgroundColor), 1.0f }, + .clear = !ibl || !app.viewOptions.skyboxEnabled }); }; FilamentApp& filamentApp = FilamentApp::get(); diff --git a/samples/heightfield.cpp b/samples/heightfield.cpp index e82bd493d1..855dabfc18 100644 --- a/samples/heightfield.cpp +++ b/samples/heightfield.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ using MinFilter = TextureSampler::MinFilter; using MagFilter = TextureSampler::MagFilter; struct App { + Skybox* skybox = nullptr; VertexBuffer* vb = nullptr; IndexBuffer* ib = nullptr; Material* mat = nullptr; @@ -296,7 +298,8 @@ int main(int argc, char** argv) { TextureSampler sampler(MinFilter::LINEAR, MagFilter::LINEAR); // Set up view - view->setClearColor({0.03f, 0.04f, 0.36f, 1.0f}); + app.skybox = Skybox::Builder().color({0.03f, 0.04f, 0.36f, 1.0f}).build(*engine); + scene->setSkybox(app.skybox); view->setPostProcessingEnabled(false); // Generate heightfield vertices. @@ -380,6 +383,7 @@ int main(int argc, char** argv) { }; auto cleanup = [&app](Engine* engine, View*, Scene*) { + engine->destroy(app.skybox); engine->destroy(app.renderable); engine->destroy(app.matInstance); engine->destroy(app.mat); diff --git a/samples/hellotriangle.cpp b/samples/hellotriangle.cpp index a8f24fc1e8..1d63e23dca 100644 --- a/samples/hellotriangle.cpp +++ b/samples/hellotriangle.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ struct App { IndexBuffer* ib; Material* mat; Camera* cam; + Skybox* skybox; Entity renderable; }; @@ -66,7 +68,8 @@ int main(int argc, char** argv) { App app; auto setup = [&app](Engine* engine, View* view, Scene* scene) { - view->setClearColor({0.1, 0.125, 0.25, 1.0}); + app.skybox = Skybox::Builder().color({0.1, 0.125, 0.25, 1.0}).build(*engine); + scene->setSkybox(app.skybox); view->setPostProcessingEnabled(false); static_assert(sizeof(Vertex) == 12, "Strange vertex size."); app.vb = VertexBuffer::Builder() @@ -102,6 +105,7 @@ int main(int argc, char** argv) { }; auto cleanup = [&app](Engine* engine, View*, Scene*) { + engine->destroy(app.skybox); engine->destroy(app.renderable); engine->destroy(app.mat); engine->destroy(app.vb); diff --git a/samples/point_sprites.cpp b/samples/point_sprites.cpp index 54fd14ea2d..6a89f9ff7b 100644 --- a/samples/point_sprites.cpp +++ b/samples/point_sprites.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,7 @@ struct App { Material* mat; MaterialInstance* matInstance; Camera* cam; + Skybox* skybox; Texture* tex; Entity renderable; }; @@ -154,10 +156,13 @@ void setup(App& app, Engine* engine, View* view, Scene* scene) { scene->addEntity(app.renderable); app.cam = engine->createCamera(); view->setCamera(app.cam); - view->setClearColor({0.1, 0.125, 0.25, 1.0}); + + app.skybox = Skybox::Builder().color({0.1, 0.125, 0.25, 1.0}).build(*engine); + scene->setSkybox(app.skybox); }; void cleanup(App& app, Engine* engine) { + engine->destroy(app.skybox); engine->destroy(app.renderable); engine->destroy(app.matInstance); engine->destroy(app.mat); diff --git a/samples/shadowtest.cpp b/samples/shadowtest.cpp index 2b156e2e0b..d3a022e96d 100644 --- a/samples/shadowtest.cpp +++ b/samples/shadowtest.cpp @@ -46,6 +46,7 @@ struct GroundPlane { }; struct App { + Skybox* skybox; utils::Entity light; std::map materials; MeshAssimp* meshes; @@ -102,8 +103,8 @@ int main(int argc, char** argv) { scene->addEntity(app.light); // Hide skybox and add ground plane. - scene->setSkybox(nullptr); - view->setClearColor({0.5f,0.75f,1.0f,1.0f}); + app.skybox = Skybox::Builder().color({0.5f,0.75f,1.0f,1.0f}).build(*engine); + scene->setSkybox(app.skybox); app.plane = createGroundPlane(engine); scene->addEntity(app.plane.renderable); }; @@ -114,6 +115,7 @@ int main(int argc, char** argv) { engine->destroy(app.plane.vb); engine->destroy(app.plane.ib); engine->destroy(app.light); + engine->destroy(app.skybox); for (auto& item : app.materials) { engine->destroy(item.second); } diff --git a/samples/strobecolor.cpp b/samples/strobecolor.cpp index bda67b681a..aa394141c3 100644 --- a/samples/strobecolor.cpp +++ b/samples/strobecolor.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -29,21 +30,23 @@ int main(int argc, char** argv) { Config config; config.title = "strobecolor"; config.backend = Engine::Backend::VULKAN; + Skybox* skybox; - auto setup = [](Engine*, View* view, Scene*) { - view->setClearColor({0.0, 0.25, 0.5, 1.0}); + auto setup = [&skybox](Engine* engine, View* view, Scene* scene) { + skybox = Skybox::Builder().color({ 0.0, 0.25, 0.5, 1.0 }).build(*engine); + scene->setSkybox(skybox); view->setPostProcessingEnabled(false); }; auto cleanup = [](Engine*, View*, Scene*) { }; - FilamentApp::get().animate([](Engine*, View* view, double now) { + FilamentApp::get().animate([skybox](Engine*, View* view, double now) { constexpr float SPEED = 4; float r = 0.5f + 0.5f * std::sin(SPEED * now); float g = 0.5f + 0.5f * std::sin(SPEED * now + M_PI * 2 / 3); float b = 0.5f + 0.5f * std::sin(SPEED * now + M_PI * 4 / 3); - view->setClearColor({r, g, b, 1.0}); + skybox->setColor({r, g, b, 1.0}); }); FilamentApp::get().run(config, setup, cleanup); diff --git a/samples/texturedquad.cpp b/samples/texturedquad.cpp index a19d3ef1d4..bfffa3d5e2 100644 --- a/samples/texturedquad.cpp +++ b/samples/texturedquad.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ struct App { Material* mat; MaterialInstance* matInstance; Camera* cam; + Skybox* skybox; Texture* tex; Entity renderable; }; @@ -108,7 +110,9 @@ int main(int argc, char** argv) { TextureSampler sampler(MinFilter::LINEAR, MagFilter::LINEAR); // Set up view - view->setClearColor({0.1, 0.125, 0.25, 1.0}); + app.skybox = Skybox::Builder().color({0.1, 0.125, 0.25, 1.0}).build(*engine); + scene->setSkybox(app.skybox); + view->setPostProcessingEnabled(false); app.cam = engine->createCamera(); view->setCamera(app.cam); @@ -147,6 +151,7 @@ int main(int argc, char** argv) { }; auto cleanup = [&app](Engine* engine, View*, Scene*) { + engine->destroy(app.skybox); engine->destroy(app.renderable); engine->destroy(app.matInstance); engine->destroy(app.mat); diff --git a/samples/viewtest.cpp b/samples/viewtest.cpp index 3c02f1a700..c9098f86d8 100644 --- a/samples/viewtest.cpp +++ b/samples/viewtest.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -30,6 +31,7 @@ struct App { VertexBuffer* vb; IndexBuffer* ib; Camera* cam; + Skybox* skybox; utils::Entity renderable; }; @@ -43,7 +45,8 @@ int main(int argc, char** argv) { App app; auto setup = [&app](Engine* engine, View* view, Scene* scene) { - view->setClearColor({0, 0, 1, 1}); + app.skybox = Skybox::Builder().color({ 0, 0, 1, 1 }).build(*engine); + scene->setSkybox(app.skybox); view->setViewport({100, 100, 512, 512}); app.vb = VertexBuffer::Builder() .vertexCount(3).bufferCount(1) @@ -66,6 +69,7 @@ int main(int argc, char** argv) { }; auto cleanup = [&app](Engine* engine, View*, Scene*) { + engine->destroy(app.skybox); engine->destroy(app.renderable); engine->destroy(app.vb); engine->destroy(app.ib); diff --git a/web/filament-js/jsbindings.cpp b/web/filament-js/jsbindings.cpp index 39bb064443..8a7135c7aa 100644 --- a/web/filament-js/jsbindings.cpp +++ b/web/filament-js/jsbindings.cpp @@ -489,7 +489,6 @@ class_("View") .function("setCamera", &View::setCamera, allow_raw_pointers()) .function("getViewport", &View::getViewport) .function("setViewport", &View::setViewport) - .function("setClearColor", &View::setClearColor) .function("setPostProcessingEnabled", &View::setPostProcessingEnabled) .function("_setAmbientOcclusionOptions", &View::setAmbientOcclusionOptions) .function("_setBloomOptions", &View::setBloomOptions)