Lit Materials can now specify the quality of SH computations
The number of SH bands used for the indirect light irradiance computations can be set to 1, 2 or 3 (default) in Material::Builder. For e.g. in lower-end devices w/ non HDR content, it might be beneficial to set this value to 2. BUGS=[341971013]
This commit is contained in:
committed by
Mathias Agopian
parent
e04c6d406f
commit
213eb6af9e
@@ -25,12 +25,17 @@ using namespace filament;
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_Material_nBuilderBuild(JNIEnv *env, jclass,
|
||||
jlong nativeEngine, jobject buffer_, jint size) {
|
||||
jlong nativeEngine, jobject buffer_, jint size, jint shBandCount) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
AutoBuffer buffer(env, buffer_, size);
|
||||
Material* material = Material::Builder()
|
||||
auto builder = Material::Builder();
|
||||
if (shBandCount) {
|
||||
builder.sphericalHarmonicsBandCount(shBandCount);
|
||||
}
|
||||
Material* material = builder
|
||||
.package(buffer.getData(), buffer.getSize())
|
||||
.build(*engine);
|
||||
|
||||
return (jlong) material;
|
||||
}
|
||||
|
||||
|
||||
@@ -346,6 +346,7 @@ public class Material {
|
||||
public static class Builder {
|
||||
private Buffer mBuffer;
|
||||
private int mSize;
|
||||
private int mShBandCount = 0;
|
||||
|
||||
/**
|
||||
* Specifies the material data. The material data is a binary blob produced by
|
||||
@@ -361,6 +362,22 @@ public class Material {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the quality of the indirect lights computations. This is only taken into account
|
||||
* if this material is lit and in the surface domain. This setting will affect the
|
||||
* IndirectLight computation if one is specified on the Scene and Spherical Harmonics
|
||||
* are used for the irradiance.
|
||||
*
|
||||
* @param shBandCount Number of spherical harmonic bands. Must be 1, 2 or 3 (default).
|
||||
* @return Reference to this Builder for chaining calls.
|
||||
* @see IndirectLight
|
||||
*/
|
||||
@NonNull
|
||||
public Builder sphericalHarmonicsBandCount(@IntRange(from = 0) int shBandCount) {
|
||||
mShBandCount = shBandCount;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns the Material object.
|
||||
*
|
||||
@@ -372,7 +389,8 @@ public class Material {
|
||||
*/
|
||||
@NonNull
|
||||
public Material build(@NonNull Engine engine) {
|
||||
long nativeMaterial = nBuilderBuild(engine.getNativeObject(), mBuffer, mSize);
|
||||
long nativeMaterial = nBuilderBuild(engine.getNativeObject(),
|
||||
mBuffer, mSize, mShBandCount);
|
||||
if (nativeMaterial == 0) throw new IllegalStateException("Couldn't create Material");
|
||||
return new Material(nativeMaterial);
|
||||
}
|
||||
@@ -1023,7 +1041,7 @@ public class Material {
|
||||
mNativeObject = 0;
|
||||
}
|
||||
|
||||
private static native long nBuilderBuild(long nativeEngine, @NonNull Buffer buffer, int size);
|
||||
private static native long nBuilderBuild(long nativeEngine, @NonNull Buffer buffer, int size, int shBandCount);
|
||||
private static native long nCreateInstance(long nativeMaterial);
|
||||
private static native long nCreateInstanceWithName(long nativeMaterial, @NonNull String name);
|
||||
private static native long nGetDefaultInstance(long nativeMaterial);
|
||||
|
||||
@@ -158,6 +158,8 @@ public:
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
*
|
||||
* @see Material::Builder::sphericalHarmonicsBandCount()
|
||||
*
|
||||
* @note
|
||||
* Because the coefficients are pre-scaled, `sh[0]` is the environment's
|
||||
* average irradiance.
|
||||
|
||||
@@ -140,6 +140,18 @@ public:
|
||||
return constant(name, strlen(name), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the quality of the indirect lights computations. This is only taken into account
|
||||
* if this material is lit and in the surface domain. This setting will affect the
|
||||
* IndirectLight computation if one is specified on the Scene and Spherical Harmonics
|
||||
* are used for the irradiance.
|
||||
*
|
||||
* @param shBandCount Number of spherical harmonic bands. Must be 1, 2 or 3 (default).
|
||||
* @return Reference to this Builder for chaining calls.
|
||||
* @see IndirectLight
|
||||
*/
|
||||
Builder& sphericalHarmonicsBandCount(size_t shBandCount) noexcept;
|
||||
|
||||
/**
|
||||
* Creates the Material object and returns a pointer to it.
|
||||
*
|
||||
|
||||
@@ -119,6 +119,7 @@ struct Material::BuilderDetails {
|
||||
const void* mPayload = nullptr;
|
||||
size_t mSize = 0;
|
||||
bool mDefaultMaterial = false;
|
||||
bool mShBandsCount = 3;
|
||||
std::unordered_map<
|
||||
utils::CString,
|
||||
std::variant<int32_t, float, bool>,
|
||||
@@ -143,6 +144,11 @@ Material::Builder& Material::Builder::package(const void* payload, size_t size)
|
||||
return *this;
|
||||
}
|
||||
|
||||
Material::Builder& Material::Builder::sphericalHarmonicsBandCount(size_t shBandCount) noexcept {
|
||||
mImpl->mShBandsCount = math::clamp(shBandCount, size_t(1), size_t(3));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, typename>
|
||||
Material::Builder& Material::Builder::constant(const char* name, size_t nameLength, T value) {
|
||||
FILAMENT_CHECK_PRECONDITION(name != nullptr) << "name cannot be null";
|
||||
@@ -897,6 +903,8 @@ void FMaterial::processSpecializationConstants(FEngine& engine, Material::Builde
|
||||
mSpecializationConstants.push_back({
|
||||
+ReservedSpecializationConstants::CONFIG_STEREO_EYE_COUNT,
|
||||
(int)engine.getConfig().stereoscopicEyeCount });
|
||||
mSpecializationConstants.push_back({
|
||||
+ReservedSpecializationConstants::CONFIG_SH_BANDS_COUNT, builder->mShBandsCount });
|
||||
if (UTILS_UNLIKELY(parser->getShaderLanguage() == ShaderLanguage::ESSL1)) {
|
||||
// The actual value of this spec-constant is set in the OpenGLDriver backend.
|
||||
mSpecializationConstants.push_back({
|
||||
|
||||
@@ -70,6 +70,7 @@ enum class ReservedSpecializationConstants : uint8_t {
|
||||
CONFIG_DEBUG_DIRECTIONAL_SHADOWMAP = 6,
|
||||
CONFIG_DEBUG_FROXEL_VISUALIZATION = 7,
|
||||
CONFIG_STEREO_EYE_COUNT = 8, // don't change (hardcoded in ShaderCompilerService.cpp)
|
||||
CONFIG_SH_BANDS_COUNT = 9
|
||||
};
|
||||
|
||||
enum class PushConstantIds : uint8_t {
|
||||
|
||||
@@ -332,6 +332,9 @@ utils::io::sstream& CodeGenerator::generateProlog(utils::io::sstream& out, Shade
|
||||
generateSpecializationConstant(out, "CONFIG_STEREO_EYE_COUNT",
|
||||
+ReservedSpecializationConstants::CONFIG_STEREO_EYE_COUNT, material.stereoscopicEyeCount);
|
||||
|
||||
generateSpecializationConstant(out, "CONFIG_SH_BANDS_COUNT",
|
||||
+ReservedSpecializationConstants::CONFIG_SH_BANDS_COUNT, 3);
|
||||
|
||||
// CONFIG_MAX_STEREOSCOPIC_EYES is used to size arrays and on Adreno GPUs + vulkan, this has to
|
||||
// be explicitly, statically defined (as in #define). Otherwise (using const int for
|
||||
// example), we'd run into a GPU crash.
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
// Image based lighting configuration
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Number of spherical harmonics bands (1, 2 or 3)
|
||||
#define SPHERICAL_HARMONICS_BANDS 3
|
||||
|
||||
// IBL integration algorithm
|
||||
#define IBL_INTEGRATION_PREFILTERED_CUBEMAP 0
|
||||
#define IBL_INTEGRATION_IMPORTANCE_SAMPLING 1
|
||||
@@ -44,21 +41,25 @@ vec3 prefilteredDFG(float perceptualRoughness, float NoV) {
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
vec3 Irradiance_SphericalHarmonics(const vec3 n) {
|
||||
return max(
|
||||
frameUniforms.iblSH[0]
|
||||
#if SPHERICAL_HARMONICS_BANDS >= 2
|
||||
+ frameUniforms.iblSH[1] * (n.y)
|
||||
+ frameUniforms.iblSH[2] * (n.z)
|
||||
+ frameUniforms.iblSH[3] * (n.x)
|
||||
#endif
|
||||
#if SPHERICAL_HARMONICS_BANDS >= 3
|
||||
+ frameUniforms.iblSH[4] * (n.y * n.x)
|
||||
+ frameUniforms.iblSH[5] * (n.y * n.z)
|
||||
+ frameUniforms.iblSH[6] * (3.0 * n.z * n.z - 1.0)
|
||||
+ frameUniforms.iblSH[7] * (n.z * n.x)
|
||||
+ frameUniforms.iblSH[8] * (n.x * n.x - n.y * n.y)
|
||||
#endif
|
||||
, 0.0);
|
||||
vec3 sphericalHarmonics = frameUniforms.iblSH[0];
|
||||
|
||||
if (CONFIG_SH_BANDS_COUNT >= 2) {
|
||||
sphericalHarmonics +=
|
||||
frameUniforms.iblSH[1] * (n.y)
|
||||
+ frameUniforms.iblSH[2] * (n.z)
|
||||
+ frameUniforms.iblSH[3] * (n.x);
|
||||
}
|
||||
|
||||
if (CONFIG_SH_BANDS_COUNT >= 3) {
|
||||
sphericalHarmonics +=
|
||||
frameUniforms.iblSH[4] * (n.y * n.x)
|
||||
+ frameUniforms.iblSH[5] * (n.y * n.z)
|
||||
+ frameUniforms.iblSH[6] * (3.0 * n.z * n.z - 1.0)
|
||||
+ frameUniforms.iblSH[7] * (n.z * n.x)
|
||||
+ frameUniforms.iblSH[8] * (n.x * n.x - n.y * n.y);
|
||||
}
|
||||
|
||||
return max(sphericalHarmonics, 0.0);
|
||||
}
|
||||
|
||||
vec3 Irradiance_RoughnessOne(const vec3 n) {
|
||||
|
||||
Reference in New Issue
Block a user