/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef IBL_CUBEMAPSH_H #define IBL_CUBEMAPSH_H #include #include #include #include #include namespace utils { class JobSystem; } // namespace utils namespace filament { namespace ibl { class Cubemap; /** * Computes spherical harmonics */ class CubemapSH { public: /** * Spherical Harmonics decomposition of the given cubemap * Optionally calculates irradiance by convolving with truncated cos. */ static std::unique_ptr computeSH( utils::JobSystem& js, const Cubemap& cm, size_t numBands, bool irradiance); /** * Render given spherical harmonics into a cubemap */ static void renderSH(utils::JobSystem& js, Cubemap& cm, const std::unique_ptr& sh, size_t numBands); static void windowSH(std::unique_ptr& sh, size_t numBands, float cutoff); /** * Compute spherical harmonics of the irradiance of the given cubemap. * The SH basis are pre-scaled for easier rendering by the shader. The resulting coefficients * are not spherical harmonics (as they're scalled by various factors). In particular they * cannot be rendered with renderSH() above. Instead use renderPreScaledSH3Bands() which * is exactly the code ran by our shader. */ static void preprocessSHForShader(std::unique_ptr& sh); /** * Render pre-scaled irrandiance SH */ static void renderPreScaledSH3Bands(utils::JobSystem& js, Cubemap& cm, const std::unique_ptr& sh); static constexpr size_t getShIndex(ssize_t m, size_t l) { return SHindex(m, l); } private: class float5 { float v[5]; public: float5() = default; constexpr float5(float a, float b, float c, float d, float e) : v{ a, b, c, d, e } {} constexpr float operator[](size_t i) const { return v[i]; } float& operator[](size_t i) { return v[i]; } }; static inline const float5 multiply(const float5 M[5], float5 x) noexcept { return float5{ M[0][0] * x[0] + M[1][0] * x[1] + M[2][0] * x[2] + M[3][0] * x[3] + M[4][0] * x[4], M[0][1] * x[0] + M[1][1] * x[1] + M[2][1] * x[2] + M[3][1] * x[3] + M[4][1] * x[4], M[0][2] * x[0] + M[1][2] * x[1] + M[2][2] * x[2] + M[3][2] * x[3] + M[4][2] * x[4], M[0][3] * x[0] + M[1][3] * x[1] + M[2][3] * x[2] + M[3][3] * x[3] + M[4][3] * x[4], M[0][4] * x[0] + M[1][4] * x[1] + M[2][4] * x[2] + M[3][4] * x[3] + M[4][4] * x[4] }; }; static inline constexpr size_t SHindex(ssize_t m, size_t l) { return l * (l + 1) + m; } static void computeShBasis(float* SHb, size_t numBands, const math::float3& s); static float Kml(ssize_t m, size_t l); static std::vector Ki(size_t numBands); static constexpr float computeTruncatedCosSh(size_t l); static float sincWindow(size_t l, float w); static math::float3 rotateShericalHarmonicBand1(math::float3 band1, math::mat3f const& M); static float5 rotateShericalHarmonicBand2(float5 const& band2, math::mat3f const& M); // debugging only... static float Legendre(ssize_t l, ssize_t m, float x); static float TSH(int l, int m, const math::float3& d); static void printShBase(std::ostream& out, int l, int m); }; } // namespace ibl } // namespace filament #endif /* IBL_CUBEMAPSH_H */