diff --git a/android/filament-android/src/main/cpp/SkyBox.cpp b/android/filament-android/src/main/cpp/SkyBox.cpp index 9362b149b2..6b31d27a32 100644 --- a/android/filament-android/src/main/cpp/SkyBox.cpp +++ b/android/filament-android/src/main/cpp/SkyBox.cpp @@ -47,6 +47,13 @@ Java_com_google_android_filament_Skybox_nBuilderShowSun(JNIEnv *env, jclass type builder->showSun(show); } +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_Skybox_nBuilderIntensity(JNIEnv *env, jclass clazz, + jlong nativeSkyBoxBuilder, jfloat intensity) { + Skybox::Builder *builder = (Skybox::Builder *) nativeSkyBoxBuilder; + builder->intensity(intensity); +} + extern "C" JNIEXPORT jlong JNICALL Java_com_google_android_filament_Skybox_nBuilderBuild(JNIEnv *env, jclass type, jlong nativeSkyBoxBuilder, jlong nativeEngine) { @@ -68,3 +75,10 @@ Java_com_google_android_filament_Skybox_nGetLayerMask(JNIEnv *env, jclass type, Skybox *skybox = (Skybox *) nativeSkybox; return static_cast(skybox->getLayerMask()); } + +extern "C" JNIEXPORT jfloat JNICALL +Java_com_google_android_filament_Skybox_nGetIntensity(JNIEnv *env, jclass clazz, + jlong nativeSkybox) { + Skybox *skybox = (Skybox *) nativeSkybox; + return static_cast(skybox->getIntensity()); +} 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 a8d25c34ed..b5d989147f 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 @@ -21,6 +21,31 @@ import android.support.annotation.NonNull; import com.google.android.filament.proguard.UsedByReflection; +/** + * Skybox + *

When added to a {@link Scene}, the Skybox fills all untouched pixels.

+ * + *

Creation and destruction

+ * + * A Skybox object is created using the {@link Skybox.Builder} and destroyed by calling + * {@link Engine#destroySkybox}.
+ *
+ *  Engine engine = Engine.create();
+ *
+ *  Scene scene = engine.createScene();
+ *
+ *  Skybox skybox = new Skybox.Builder()
+ *              .environment(cubemap)
+ *              .build(engine);
+ *
+ *  scene.setSkybox(skybox);
+ * 
+ * + * Currently only {@link Texture} based sky boxes are supported. + * + * @see Scene + * @see IndirectLight + */ public class Skybox { private long mNativeObject; @@ -29,28 +54,88 @@ public class Skybox { mNativeObject = nativeSkybox; } + + /** + * Use {@link #Builder} to construct a Skybox object instance. + */ public static class Builder { @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) // Keep to finalize native resources private final BuilderFinalizer mFinalizer; private final long mNativeBuilder; + /** + * Use {@link #Builder} to construct a Skybox object instance. + */ public Builder() { mNativeBuilder = nCreateBuilder(); mFinalizer = new BuilderFinalizer(mNativeBuilder); } + /** + * Set the environment map (i.e. the skybox content). + * + *

The Skybox is rendered as though it were an infinitely large cube with the + * camera inside it. This means that the cubemap which is mapped onto the cube's exterior + * will appear mirrored. This follows the OpenGL conventions.

+ * + *

The cmgen tool generates reflection maps by default which are therefore + * ideal to use as skyboxes.

+ * + * @param cubemap A cubemap {@link Texture} + * + * @return This Builder, for chaining calls. + * + * @see Texture + */ @NonNull - public Builder environment(@NonNull Texture texture) { - nBuilderEnvironment(mNativeBuilder, texture.getNativeObject()); + public Builder environment(@NonNull Texture cubemap) { + nBuilderEnvironment(mNativeBuilder, cubemap.getNativeObject()); return this; } + /** + * Indicates whether the sun should be rendered. The sun can only be + * rendered if there is at least one light of type {@link LightManager.Type#SUN} in + * the {@link Scene}. The default value is false. + * + * @param show true if the sun should be rendered, false otherwise + * + * @return This Builder, for chaining calls. + */ @NonNull public Builder showSun(boolean show) { nBuilderShowSun(mNativeBuilder, show); return this; } + /** + * Sets the Skybox intensity when no {@link IndirectLight} is set + * + *

This call is ignored when an {@link IndirectLight} is set, otherwise it is used in + * its place.

+ * + * @param envIntensity Scale factor applied to the skybox texel values such that + * the result is in cd/m2 (lux) units (default = 30000) + * + * @return This Builder, for chaining calls. + * + * @see IndirectLight.Builder#intensity + */ + @NonNull + public Builder intensity(float envIntensity) { + nBuilderIntensity(mNativeBuilder, envIntensity); + return this; + } + + /** + * Creates a Skybox object + * + * @param engine the {@link Engine} to associate this Skybox with. + * + * @return A newly created Skyboxobject + * + * @exception IllegalStateException can be thrown if the Skybox couldn't be created + */ @NonNull public Skybox build(@NonNull Engine engine) { long nativeSkybox = nBuilderBuild(mNativeBuilder, engine.getNativeObject()); @@ -75,14 +160,35 @@ public class Skybox { } } - public void setLayerMask(@IntRange(from = 0, to = 255) int select, @IntRange(from = 0, to = 255) int value) { - nSetLayerMask(getNativeObject(), select & 0xff, value & 0xff); + /** + * Sets bits in a visibility mask. By default, this is 0x1. + *

This provides a simple mechanism for hiding or showing this Skybox in a + * {@link Scene}.

+ * + *

For example, to set bit 1 and reset bits 0 and 2 while leaving all other bits unaffected, + * call: setLayerMask(7, 2).

+ * + * @param select the set of bits to affect + * @param values the replacement values for the affected bits + * + * @see View#setVisibleLayers + */ + public void setLayerMask(@IntRange(from = 0, to = 255) int select, @IntRange(from = 0, to = 255) int values) { + nSetLayerMask(getNativeObject(), select & 0xff, values & 0xff); } + /** + * @return the visibility mask bits + */ public int getLayerMask() { return nGetLayerMask(getNativeObject()); } + /** + * Returns the Skybox's intensity in cd/m2. + */ + public float getIntensity() { return nGetIntensity(getNativeObject()); } + public long getNativeObject() { if (mNativeObject == 0) { throw new IllegalStateException("Calling method on destroyed Skybox"); @@ -98,7 +204,9 @@ public class Skybox { private static native void nDestroyBuilder(long nativeSkyboxBuilder); 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 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); } diff --git a/filament/include/filament/Skybox.h b/filament/include/filament/Skybox.h index 4e53f0cda9..d453e6779a 100644 --- a/filament/include/filament/Skybox.h +++ b/filament/include/filament/Skybox.h @@ -134,8 +134,24 @@ public: friend class details::FSkybox; }; + /** + * Sets bits in a visibility mask. By default, this is 0x1. + * + * This provides a simple mechanism for hiding or showing this Skybox in a Scene. + * + * @see View::setVisibleLayers(). + * + * For example, to set bit 1 and reset bits 0 and 2 while leaving all other bits unaffected, + * call: `setLayerMask(7, 2)`. + * + * @param select the set of bits to affect + * @param values the replacement values for the affected bits + */ void setLayerMask(uint8_t select, uint8_t values) noexcept; + /** + * @return the visibility mask bits + */ uint8_t getLayerMask() const noexcept; /**