From 6620edebb3c61dadc98f55a2f2866f28d6bf5bb0 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 12 Jun 2019 18:30:14 -0700 Subject: [PATCH] Add IndirectLight::radiance() This allows to specify the irradiance by providing only the radiance as SH, which might be easier in some case. --- .../src/main/cpp/IndirectLight.cpp | 9 ++++++ .../android/filament/IndirectLight.java | 19 +++++++++++ filament/include/filament/IndirectLight.h | 32 +++++++++++++++++++ filament/src/IndirectLight.cpp | 20 ++++++++++++ 4 files changed, 80 insertions(+) diff --git a/android/filament-android/src/main/cpp/IndirectLight.cpp b/android/filament-android/src/main/cpp/IndirectLight.cpp index c19a5ea93d..e0767b563f 100644 --- a/android/filament-android/src/main/cpp/IndirectLight.cpp +++ b/android/filament-android/src/main/cpp/IndirectLight.cpp @@ -57,6 +57,15 @@ Java_com_google_android_filament_IndirectLight_nIrradiance(JNIEnv* env, jclass, env->ReleaseFloatArrayElements(sh_, sh, JNI_ABORT); } +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_IndirectLight_nRadiance(JNIEnv* env, jclass, + jlong nativeBuilder, jint bands, jfloatArray sh_) { + IndirectLight::Builder* builder = (IndirectLight::Builder*) nativeBuilder; + jfloat* sh = env->GetFloatArrayElements(sh_, NULL); + builder->radiance((uint8_t) bands, (const filament::math::float3*) sh); + env->ReleaseFloatArrayElements(sh_, sh, JNI_ABORT); +} + extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_IndirectLight_nIrradianceAsTexture(JNIEnv*, jclass, jlong nativeBuilder, jlong nativeTexture) { 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 41caee4b9c..31fffcb5e7 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 @@ -61,6 +61,24 @@ public class IndirectLight { return this; } + @NonNull + public Builder radiance(@IntRange(from=1, to=3) int bands, @NonNull float[] sh) { + switch (bands) { + case 1: if (sh.length < 3) + throw new ArrayIndexOutOfBoundsException( + "1 band SH, array must be at least 1 x float3"); else break; + case 2: if (sh.length < 4 * 3) + throw new ArrayIndexOutOfBoundsException( + "2 bands SH, array must be at least 4 x float3"); else break; + case 3: if (sh.length < 9 * 3) + throw new ArrayIndexOutOfBoundsException( + "3 bands SH, array must be at least 9 x float3"); else break; + default: throw new IllegalArgumentException("bands must be 1, 2 or 3"); + } + nRadiance(mNativeBuilder, bands, sh); + return this; + } + @NonNull public Builder irradiance(@NonNull Texture cubemap) { nIrradianceAsTexture(mNativeBuilder, cubemap.getNativeObject()); @@ -138,6 +156,7 @@ public class IndirectLight { private static native long nBuilderBuild(long nativeBuilder, long nativeEngine); private static native void nBuilderReflections(long nativeBuilder, long nativeTexture); private static native void nIrradiance(long nativeBuilder, int bands, float[] sh); + private static native void nRadiance(long nativeBuilder, int bands, float[] sh); private static native void nIrradianceAsTexture(long nativeBuilder, long nativeTexture); private static native void nIntensity(long nativeBuilder, float envIntensity); private static native void nRotation(long nativeBuilder, float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8) ; diff --git a/filament/include/filament/IndirectLight.h b/filament/include/filament/IndirectLight.h index 9d72274b45..8a48dbca9c 100644 --- a/filament/include/filament/IndirectLight.h +++ b/filament/include/filament/IndirectLight.h @@ -173,6 +173,38 @@ public: */ Builder& irradiance(uint8_t bands, math::float3 const* sh) noexcept; + /** + * Sets the irradiance from the radiance expressed as Spherical Harmonics. + * + * The radiance must be specified as Spherical Harmonics coefficients \f$ L_{l}^{m} + * + * The index in the \p sh array is given by: + * + * `index(l, m) = l * (l + 1) + m` + * + * \f$ sh[index(l,m)] = L_{l}^{m} \f$ + * + * index | l | m + * :-----:|:---:|:---: + * 0 | 0 | 0 + * 1 | 1 | -1 + * 2 | ^ | 0 + * 3 | ^ | 1 + * 4 | 2 | -2 + * 5 | ^ | -1 + * 6 | ^ | 0 + * 7 | ^ | 1 + * 8 | ^ | 2 + * + * @param bands Number of spherical harmonics bands. Must be 1, 2 or 3. + * @param sh Array containing the spherical harmonics coefficients. + * The size of the array must be \f$ bands^{2} \f$. + * (i.e. 1, 4 or 9 coefficients respectively). + * + * @return This Builder, for chaining calls. + */ + Builder& radiance(uint8_t bands, math::float3 const* sh) noexcept; + /** * Sets the irradiance as a cubemap. * diff --git a/filament/src/IndirectLight.cpp b/filament/src/IndirectLight.cpp index 4da831ced1..ea41602f6c 100644 --- a/filament/src/IndirectLight.cpp +++ b/filament/src/IndirectLight.cpp @@ -67,6 +67,26 @@ IndirectLight::Builder& IndirectLight::Builder::irradiance(uint8_t bands, float3 return *this; } +IndirectLight::Builder& IndirectLight::Builder::radiance(uint8_t bands, float3 const* sh) noexcept { + float3 irradiance[9]; + if (bands >= 1) { + irradiance[0] = sh[0] * 0.282095; + if (bands >= 2) { + irradiance[1] = sh[1] * 0.325735; + irradiance[2] = sh[2] * 0.325735; + irradiance[3] = sh[3] * 0.325735; + if (bands >= 3) { + irradiance[4] = sh[4] * 0.045523; + irradiance[5] = sh[5] * 0.091046; + irradiance[6] = sh[6] * 0.157696; + irradiance[7] = sh[7] * 0.091046; + irradiance[8] = sh[8] * 0.045523; + } + } + } + return this->irradiance(bands, irradiance); +} + IndirectLight::Builder& IndirectLight::Builder::irradiance(Texture const* cubemap) noexcept { mImpl->mIrradianceMap = cubemap; return *this;