From 732a6c08dea774379d8d092050c35fe4b977b03a Mon Sep 17 00:00:00 2001 From: Philip Rideout Date: Fri, 7 Aug 2020 08:50:57 -0700 Subject: [PATCH] Add Texture getters to IndirectLight and Skybox. Fixes #2851. --- RELEASE_NOTES.md | 2 ++ .../src/main/cpp/IndirectLight.cpp | 16 ++++++++++++++ .../filament-android/src/main/cpp/SkyBox.cpp | 8 +++++++ .../android/filament/IndirectLight.java | 15 +++++++++++++ .../com/google/android/filament/Skybox.java | 11 ++++++++++ filament/include/filament/IndirectLight.h | 10 +++++++++ filament/include/filament/Skybox.h | 5 +++++ filament/src/IndirectLight.cpp | 21 ++++++++++++++++--- filament/src/Skybox.cpp | 3 +++ filament/src/View.cpp | 4 ++-- filament/src/details/IndirectLight.h | 10 +++++---- filament/src/details/Skybox.h | 2 ++ web/filament-js/extensions.js | 2 ++ web/filament-js/filament.d.ts | 3 +++ web/filament-js/jsbindings.cpp | 11 +++++++++- 15 files changed, 113 insertions(+), 10 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index e0bb806b89..d109e1d6db 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -6,6 +6,8 @@ A new header is inserted each time a *tag* is created. ## Next release - MASKED mode now leaves destination alpha intact (useful for transparent targets). +- Fixed several memory leaks in gltfio and the JavaScript bindings. +- Added texture getters to Skybox and IndirectLight (C++, Java, JavaScript). ## v1.8.1 diff --git a/android/filament-android/src/main/cpp/IndirectLight.cpp b/android/filament-android/src/main/cpp/IndirectLight.cpp index 4c6d941acf..bd7b85498f 100644 --- a/android/filament-android/src/main/cpp/IndirectLight.cpp +++ b/android/filament-android/src/main/cpp/IndirectLight.cpp @@ -144,6 +144,22 @@ Java_com_google_android_filament_IndirectLight_nGetColorEstimate(JNIEnv* env, jc env->ReleaseFloatArrayElements(outColor_, outColor, 0); } +extern "C" JNIEXPORT jlong JNICALL +Java_com_google_android_filament_IndirectLight_nGetReflectionsTexture(JNIEnv* env, jclass, + jlong nativeIndirectLight) { + IndirectLight *indirectLight = (IndirectLight *) nativeIndirectLight; + Texture const *tex = indirectLight->getReflectionsTexture(); + return (jlong) tex; +} + +extern "C" JNIEXPORT jlong JNICALL +Java_com_google_android_filament_IndirectLight_nGetIrradianceTexture(JNIEnv* env, jclass, + jlong nativeIndirectLight) { + IndirectLight *indirectLight = (IndirectLight *) nativeIndirectLight; + Texture const *tex = indirectLight->getIrradianceTexture(); + return (jlong) tex; +} + extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_IndirectLight_nGetDirectionEstimateStatic(JNIEnv *env, jclass, jfloatArray sh_, jfloatArray outDirection_) { diff --git a/android/filament-android/src/main/cpp/SkyBox.cpp b/android/filament-android/src/main/cpp/SkyBox.cpp index 7fbd81ce32..ea61a07c14 100644 --- a/android/filament-android/src/main/cpp/SkyBox.cpp +++ b/android/filament-android/src/main/cpp/SkyBox.cpp @@ -98,3 +98,11 @@ Java_com_google_android_filament_Skybox_nSetColor(JNIEnv *, jclass, Skybox *skybox = (Skybox *) nativeSkybox; skybox->setColor({r, g, b, a}); } + +extern "C" JNIEXPORT jlong JNICALL +Java_com_google_android_filament_Skybix_nGetTexture(JNIEnv* env, jclass, + jlong nativeSkybox) { + Skybox *skybox = (Skybox *) nativeSkybox; + Texture const *tex = skybox->getTexture(); + return (jlong) tex; +} diff --git a/android/filament-android/src/main/java/com/google/android/filament/IndirectLight.java b/android/filament-android/src/main/java/com/google/android/filament/IndirectLight.java index 496d2b3dc4..2fbfe49cce 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/IndirectLight.java +++ b/android/filament-android/src/main/java/com/google/android/filament/IndirectLight.java @@ -479,6 +479,18 @@ public class IndirectLight { return colorIntensity; } + @Nullable + public Texture getReflectionsTexture() { + long nativeTexture = nGetReflectionsTexture(getNativeObject()); + return nativeTexture == 0 ? null : new Texture(nativeTexture); + } + + @Nullable + public Texture getIrradianceTexture() { + long nativeTexture = nGetIrradianceTexture(getNativeObject()); + return nativeTexture == 0 ? null : new Texture(nativeTexture); + } + public long getNativeObject() { if (mNativeObject == 0) { throw new IllegalStateException("Calling method on destroyed IndirectLight"); @@ -508,6 +520,9 @@ public class IndirectLight { private static native void nGetDirectionEstimate(long nativeIndirectLight, float[] outDirection); private static native void nGetColorEstimate(long nativeIndirectLight, float[] outColor, float x, float y, float z); + private static native long nGetReflectionsTexture(long nativeIndirectLight); + private static native long nGetIrradianceTexture(long nativeIndirectLight); + private static native void nGetDirectionEstimateStatic(float[] sh, float[] direction); private static native void nGetColorEstimateStatic(float[] colorIntensity, float[] sh, float x, float y, float z); } 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 75cec6057f..2fd1d0f7f5 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,7 @@ package com.google.android.filament; import androidx.annotation.IntRange; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.Size; import static com.google.android.filament.Colors.LinearColor; @@ -240,6 +241,15 @@ public class Skybox { */ public float getIntensity() { return nGetIntensity(getNativeObject()); } + /** + * @return the associated texture, or null if it does not exist + */ + @Nullable + public Texture getTexture() { + long nativeTexture = nGetTexture(getNativeObject()); + return nativeTexture == 0 ? null : new Texture(nativeTexture); + } + public long getNativeObject() { if (mNativeObject == 0) { throw new IllegalStateException("Calling method on destroyed Skybox"); @@ -262,4 +272,5 @@ public class Skybox { 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); + private static native long nGetTexture(long nativeSkybox); } diff --git a/filament/include/filament/IndirectLight.h b/filament/include/filament/IndirectLight.h index 9897b1c6bd..8c9ab31d3e 100644 --- a/filament/include/filament/IndirectLight.h +++ b/filament/include/filament/IndirectLight.h @@ -281,6 +281,16 @@ public: */ const math::mat3f& getRotation() const noexcept; + /** + * Returns the associated reflection map, or null if it does not exist. + */ + Texture const* getReflectionsTexture() const noexcept; + + /** + * Returns the associated irradiance map, or null if it does not exist. + */ + Texture const* getIrradianceTexture() const noexcept; + /** * Helper to estimate the direction of the dominant light in the environment represented by * spherical harmonics. diff --git a/filament/include/filament/Skybox.h b/filament/include/filament/Skybox.h index 31d0534ef4..4a0b919379 100644 --- a/filament/include/filament/Skybox.h +++ b/filament/include/filament/Skybox.h @@ -170,6 +170,11 @@ public: * Returns the skybox's intensity in cd/m^2. */ float getIntensity() const noexcept; + + /** + * @return the associated texture, or null if it does not exist + */ + Texture const* getTexture() const noexcept; }; } // namespace filament diff --git a/filament/src/IndirectLight.cpp b/filament/src/IndirectLight.cpp index 974306a630..a485e13ae4 100644 --- a/filament/src/IndirectLight.cpp +++ b/filament/src/IndirectLight.cpp @@ -174,7 +174,7 @@ IndirectLight* IndirectLight::Builder::build(Engine& engine) { FIndirectLight::FIndirectLight(FEngine& engine, const Builder& builder) noexcept { if (builder->mReflectionsMap) { - mReflectionsMapHandle = upcast(builder->mReflectionsMap)->getHwHandle(); + mReflectionsTexture = upcast(builder->mReflectionsMap); mLevelCount = builder->mReflectionsMap->getLevels(); } @@ -186,7 +186,7 @@ FIndirectLight::FIndirectLight(FEngine& engine, const Builder& builder) noexcept mRotation = builder->mRotation; mIntensity = builder->mIntensity; if (builder->mIrradianceMap) { - mIrradianceMapHandle = upcast(builder->mIrradianceMap)->getHwHandle(); + mIrradianceTexture = upcast(builder->mIrradianceMap); } else { // TODO: if needed, generate the irradiance map, this is an engine config if (FEngine::CONFIG_IBL_USE_IRRADIANCE_MAP) { @@ -197,10 +197,17 @@ FIndirectLight::FIndirectLight(FEngine& engine, const Builder& builder) noexcept void FIndirectLight::terminate(FEngine& engine) { if (FEngine::CONFIG_IBL_USE_IRRADIANCE_MAP) { FEngine::DriverApi& driver = engine.getDriverApi(); - driver.destroyTexture(mIrradianceMapHandle); + driver.destroyTexture(getIrradianceHwHandle()); } } +backend::Handle FIndirectLight::getReflectionHwHandle() const noexcept { + return mReflectionsTexture->getHwHandle(); +} + +backend::Handle FIndirectLight::getIrradianceHwHandle() const noexcept { + return mIrradianceTexture->getHwHandle(); +} math::float3 FIndirectLight::getDirectionEstimate(math::float3 const* f) noexcept { // The linear direction is found as normalize(-sh[3], -sh[1], sh[2]), but the coefficients @@ -282,6 +289,14 @@ const math::mat3f& IndirectLight::getRotation() const noexcept { return upcast(this)->getRotation(); } +Texture const* IndirectLight::getReflectionsTexture() const noexcept { + return upcast(this)->getReflectionsTexture(); +} + +Texture const* IndirectLight::getIrradianceTexture() const noexcept { + return upcast(this)->getIrradianceTexture(); +} + math::float3 IndirectLight::getDirectionEstimate() const noexcept { return upcast(this)->getDirectionEstimate(); } diff --git a/filament/src/Skybox.cpp b/filament/src/Skybox.cpp index aa896567fd..8bc0f741a8 100644 --- a/filament/src/Skybox.cpp +++ b/filament/src/Skybox.cpp @@ -169,7 +169,10 @@ float Skybox::getIntensity() const noexcept { void Skybox::setColor(math::float4 color) noexcept { upcast(this)->setColor(color); +} +Texture const* Skybox::getTexture() const noexcept { + return upcast(this)->getTexture(); } } // namespace filament diff --git a/filament/src/View.cpp b/filament/src/View.cpp index 756f223cb3..60937b6519 100644 --- a/filament/src/View.cpp +++ b/filament/src/View.cpp @@ -298,9 +298,9 @@ void FView::prepareLighting(FEngine& engine, FEngine::DriverApi& driver, ArenaSc u.setUniform(offsetof(PerViewUib, iblRoughnessOneLevel), iblRoughnessOneLevel); u.setUniform(offsetof(PerViewUib, iblLuminance), intensity * exposure); u.setUniformArray(offsetof(PerViewUib, iblSH), ibl->getSH(), 9); - if (ibl->getReflectionMap()) { + if (ibl->getReflectionHwHandle()) { mPerViewSb.setSampler(PerViewSib::IBL_SPECULAR, { - ibl->getReflectionMap(), { + ibl->getReflectionHwHandle(), { .filterMag = SamplerMagFilter::LINEAR, .filterMin = SamplerMinFilter::LINEAR_MIPMAP_LINEAR }}); diff --git a/filament/src/details/IndirectLight.h b/filament/src/details/IndirectLight.h index 4e1b8dff85..9acf75f36f 100644 --- a/filament/src/details/IndirectLight.h +++ b/filament/src/details/IndirectLight.h @@ -42,13 +42,15 @@ public: void terminate(FEngine& engine); - backend::Handle getReflectionMap() const noexcept { return mReflectionsMapHandle; } - backend::Handle getIrradianceMap() const noexcept { return mIrradianceMapHandle; } + backend::Handle getReflectionHwHandle() const noexcept; + backend::Handle getIrradianceHwHandle() const noexcept; math::float3 const* getSH() const noexcept{ return mIrradianceCoefs.data(); } float getIntensity() const noexcept { return mIntensity; } void setIntensity(float intensity) noexcept { mIntensity = intensity; } void setRotation(math::mat3f const& rotation) noexcept { mRotation = rotation; } const math::mat3f& getRotation() const noexcept { return mRotation; } + FTexture const* getReflectionsTexture() const noexcept { return mReflectionsTexture; } + FTexture const* getIrradianceTexture() const noexcept { return mIrradianceTexture; } size_t getLevelCount() const noexcept { return mLevelCount; } math::float3 getDirectionEstimate() const noexcept; math::float4 getColorEstimate(math::float3 direction) const noexcept; @@ -56,8 +58,8 @@ public: static math::float4 getColorEstimate(const math::float3 sh[9], math::float3 direction) noexcept; private: - backend::Handle mReflectionsMapHandle; - backend::Handle mIrradianceMapHandle; + FTexture const* mReflectionsTexture; + FTexture const* mIrradianceTexture; std::array mIrradianceCoefs; float mIntensity = DEFAULT_INTENSITY; math::mat3f mRotation; diff --git a/filament/src/details/Skybox.h b/filament/src/details/Skybox.h index b5f4517e6f..5304505ec8 100644 --- a/filament/src/details/Skybox.h +++ b/filament/src/details/Skybox.h @@ -49,6 +49,8 @@ public: float getIntensity() const noexcept { return mIntensity; } + FTexture const* getTexture() const noexcept { return mSkyboxTexture; } + void setColor(math::float4 color) noexcept; // commits UBOs diff --git a/web/filament-js/extensions.js b/web/filament-js/extensions.js index 307a29f5ff..77ca578157 100644 --- a/web/filament-js/extensions.js +++ b/web/filament-js/extensions.js @@ -88,6 +88,7 @@ Filament.loadClassExtensions = function() { }; /// createIblFromKtx ::method:: Utility that creates an [IndirectLight] from a KTX file. + /// NOTE: To prevent a leak, please be sure to destroy the associated reflections texture. /// buffer ::argument:: asset string, or Uint8Array, or [Buffer] with KTX file contents /// options ::argument:: Options dictionary. /// ::retval:: [IndirectLight] @@ -99,6 +100,7 @@ Filament.loadClassExtensions = function() { }; /// createSkyFromKtx ::method:: Utility function that creates a [Skybox] from a KTX file. + /// NOTE: To prevent a leak, please be sure to destroy the associated texture. /// buffer ::argument:: asset string, or Uint8Array, or [Buffer] with KTX file contents /// options ::argument:: Options dictionary. /// ::retval:: [Skybox] diff --git a/web/filament-js/filament.d.ts b/web/filament-js/filament.d.ts index 1d62f7011e..660a60f7cc 100644 --- a/web/filament-js/filament.d.ts +++ b/web/filament-js/filament.d.ts @@ -132,6 +132,7 @@ export class Entity { export class Skybox { public setColor(color: float4): void; + public getTexture(): Texture; } export class LightManager$Instance { @@ -397,6 +398,8 @@ export class IndirectLight { public getIntensity(): number; public setRotation(value: mat3): void; public getRotation(): mat3; + public getReflectionsTexture(): Texture; + public getIrradianceTexture(): Texture; public static getDirectionEstimate(f32array: any): float3; public static getColorEstimate(f32array: any, direction: float3): float4; shfloats: Array; diff --git a/web/filament-js/jsbindings.cpp b/web/filament-js/jsbindings.cpp index d3fdf6fe6a..c977d216ed 100644 --- a/web/filament-js/jsbindings.cpp +++ b/web/filament-js/jsbindings.cpp @@ -1209,6 +1209,12 @@ class_("IndirectLight") .function("getRotation", EMBIND_LAMBDA(flatmat3, (IndirectLight* self), { return flatmat3 { self->getRotation() }; }), allow_raw_pointers()) + .function("getReflectionsTexture", EMBIND_LAMBDA(Texture*, (IndirectLight* self), { + return (Texture*) self->getReflectionsTexture(); // cast away const to appease embind + }), allow_raw_pointers()) + .function("getIrradianceTexture", EMBIND_LAMBDA(Texture*, (IndirectLight* self), { + return (Texture*) self->getIrradianceTexture(); // cast away const to appease embind + }), allow_raw_pointers()) .class_function("getDirectionEstimate", EMBIND_LAMBDA(filament::math::float3, (val ta), { size_t nfloats = ta["length"].as(); std::vector floats(nfloats); @@ -1254,7 +1260,10 @@ class_("IndirectLight$Builder") class_("Skybox") .class_function("Builder", (SkyBuilder (*)()) [] { return SkyBuilder(); }) - .function("setColor", &Skybox::setColor); + .function("setColor", &Skybox::setColor) + .function("getTexture", EMBIND_LAMBDA(Texture*, (Skybox* skybox), { + return (Texture*) skybox->getTexture(); // cast away const to appease embind + }), allow_raw_pointers()); class_("Skybox$Builder") .function("_build", EMBIND_LAMBDA(Skybox*, (SkyBuilder* builder, Engine* engine), {