diff --git a/android/filamat-android/src/main/cpp/MaterialBuilder.cpp b/android/filamat-android/src/main/cpp/MaterialBuilder.cpp index e5799b0596..75fa5aea96 100644 --- a/android/filamat-android/src/main/cpp/MaterialBuilder.cpp +++ b/android/filamat-android/src/main/cpp/MaterialBuilder.cpp @@ -229,18 +229,28 @@ Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderCurvatu auto builder = (MaterialBuilder*) nativeBuilder; builder->curvatureToRoughness(curvatureToRoughness); } + extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderLimitOverInterpolation( JNIEnv* env, jclass type, jlong nativeBuilder, jboolean limitOverInterpolation) { auto builder = (MaterialBuilder*) nativeBuilder; builder->limitOverInterpolation(limitOverInterpolation); } + +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderClearCoatIorChange( + JNIEnv* env, jclass type, jlong nativeBuilder, jboolean clearCoatIorChange) { + auto builder = (MaterialBuilder*) nativeBuilder; + builder->clearCoatIorChange(clearCoatIorChange); +} + extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderFlipUV(JNIEnv* env, jclass type, jlong nativeBuilder, jboolean flipUV) { auto builder = (MaterialBuilder*) nativeBuilder; builder->flipUV(flipUV); } + extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderTransparencyMode( JNIEnv* env, jclass type, jlong nativeBuilder, jint mode) { diff --git a/android/filamat-android/src/main/java/com/google/android/filament/filamat/MaterialBuilder.java b/android/filamat-android/src/main/java/com/google/android/filament/filamat/MaterialBuilder.java index f601b98431..57e471f477 100644 --- a/android/filamat-android/src/main/java/com/google/android/filament/filamat/MaterialBuilder.java +++ b/android/filamat-android/src/main/java/com/google/android/filament/filamat/MaterialBuilder.java @@ -294,6 +294,12 @@ public class MaterialBuilder { return this; } + @NonNull + public MaterialBuilder clearCoatIorChange(boolean clearCoatIorChange) { + nMaterialBuilderClearCoatIorChange(mNativeObject, clearCoatIorChange); + return this; + } + @NonNull public MaterialBuilder flipUV(boolean flipUV) { nMaterialBuilderFlipUV(mNativeObject, flipUV); @@ -398,6 +404,8 @@ public class MaterialBuilder { boolean curvatureToRoughness); private static native void nMaterialBuilderLimitOverInterpolation(long mNativeObject, boolean limitOverInterpolation); + private static native void nMaterialBuilderClearCoatIorChange(long mNativeObject, + boolean clearCoatIorChange); private static native void nMaterialBuilderFlipUV(long nativeBuilder, boolean flipUV); private static native void nMaterialBuilderTransparencyMode(long nativeBuilder, int mode); private static native void nMaterialBuilderPlatform(long nativeBuilder, int platform); diff --git a/docs/Materials.md.html b/docs/Materials.md.html index 12c42175ed..eb4c7136ff 100644 --- a/docs/Materials.md.html +++ b/docs/Materials.md.html @@ -1093,7 +1093,7 @@ Value Description : Reduces specular aliasing by increasing roughness based on the local geometric curvature. - This property is particularly effective if you only use MSAA. + This property is particularly effective if you only use MSAA as your anti-aliasing method. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON material { @@ -1102,7 +1102,7 @@ material { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ![Figure [curvatureToRoughness]: Close up of a glossy metallic surface rendered normally (left) and -with `curvatureToRoughness` (right).](images/screenshot_curvature_to_roughness.png) +with `curvatureToRoughness` (right).](images/screenshot_curvature_to_roughness.jpg) ### limitOverInterpolation @@ -1125,6 +1125,31 @@ material { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +### clearCoatIorChange + +Type +: `boolean` + +Value +: `true` or `false`. Defaults to `true`. + +Description +: When adding a clear coat layer, the change in index of refraction (IoR) is taken into account + to modify the specular color of the base layer. This appears to darken `baseColor`. When this + effect is disabled, `baseColor` is left unmodified. See figure [clearCoatIorChange] for an + example of how this property can affect a red metallic base layer. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON +material { + clearCoatIorChange : false +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +![Figure [clearCoatIorChange]: The same rough metallic ball with a clear coat layer rendered +with `clearCoatIorChange` enabled (left) and disabled +(right).](images/screenshot_clear_coat_ior_change.jpg) + ### variantFilter Type diff --git a/docs/images/screenshot_clear_coat_ior_change.jpg b/docs/images/screenshot_clear_coat_ior_change.jpg new file mode 100644 index 0000000000..49d74fd0ca Binary files /dev/null and b/docs/images/screenshot_clear_coat_ior_change.jpg differ diff --git a/docs/images/screenshot_curvature_to_roughness.jpg b/docs/images/screenshot_curvature_to_roughness.jpg new file mode 100644 index 0000000000..02556c28f9 Binary files /dev/null and b/docs/images/screenshot_curvature_to_roughness.jpg differ diff --git a/docs/images/screenshot_curvature_to_roughness.png b/docs/images/screenshot_curvature_to_roughness.png deleted file mode 100644 index 4d8ab4ccca..0000000000 Binary files a/docs/images/screenshot_curvature_to_roughness.png and /dev/null differ diff --git a/libs/filaflat/include/filaflat/FilaflatDefs.h b/libs/filaflat/include/filaflat/FilaflatDefs.h index 3b693fe154..13d497a14d 100644 --- a/libs/filaflat/include/filaflat/FilaflatDefs.h +++ b/libs/filaflat/include/filaflat/FilaflatDefs.h @@ -68,6 +68,7 @@ enum UTILS_PUBLIC ChunkType : uint64_t { MaterialShadowMultiplier = charTo64bitNum("MAT_SHML"), MaterialCurvatureToRoughness = charTo64bitNum("MAT_CV2R"), MaterialLimitOverInterpolation = charTo64bitNum("MAT_LMOI"), + MaterialClearCoatIorChange = charTo64bitNum("MAT_CIOR"), MaterialRequiredAttributes = charTo64bitNum("MAT_REQA"), MaterialDepthWriteSet = charTo64bitNum("MAT_DEWS"), diff --git a/libs/filamat/include/filamat/MaterialBuilder.h b/libs/filamat/include/filamat/MaterialBuilder.h index 30a0bd7576..b2152922f9 100644 --- a/libs/filamat/include/filamat/MaterialBuilder.h +++ b/libs/filamat/include/filamat/MaterialBuilder.h @@ -189,6 +189,12 @@ public: // disabled by default MaterialBuilder& limitOverInterpolation(bool limitOverInterpolation) noexcept; + // enables or disables the index of refraction (IoR) change caused by the clear coat layer when + // present. When the IoR changes, the base color is darkened. Disabling this feature preserves + // the base color as initially specified + // enabled by default + MaterialBuilder& clearCoatIorChange(bool clearCoatIorChange) noexcept; + // enable/disable flipping of the Y coordinate of UV attributes, enabled by default MaterialBuilder& flipUV(bool flipUV) noexcept; @@ -305,6 +311,7 @@ private: bool mCurvatureToRoughness = false; bool mLimitOverInterpolation = false; + bool mClearCoatIorChange = true; bool mFlipUV = true; }; diff --git a/libs/filamat/src/MaterialBuilder.cpp b/libs/filamat/src/MaterialBuilder.cpp index 51969126ca..e14a7d2aa8 100644 --- a/libs/filamat/src/MaterialBuilder.cpp +++ b/libs/filamat/src/MaterialBuilder.cpp @@ -241,6 +241,11 @@ MaterialBuilder& MaterialBuilder::limitOverInterpolation(bool limitOverInterpola return *this; } +MaterialBuilder& MaterialBuilder::clearCoatIorChange(bool clearCoatIorChange) noexcept { + mClearCoatIorChange = clearCoatIorChange; + return *this; +} + MaterialBuilder& MaterialBuilder::flipUV(bool flipUV) noexcept { mFlipUV = flipUV; return *this; @@ -318,6 +323,7 @@ void MaterialBuilder::prepareToBuild(MaterialInfo& info) noexcept { info.hasExternalSamplers = hasExternalSampler(); info.curvatureToRoughness = mCurvatureToRoughness; info.limitOverInterpolation = mLimitOverInterpolation; + info.clearCoatIorChange = mClearCoatIorChange; info.flipUV = mFlipUV; info.requiredAttributes = mRequiredAttributes; info.blendingMode = mBlendingMode; @@ -422,6 +428,10 @@ Package MaterialBuilder::build() noexcept { ChunkType::MaterialLimitOverInterpolation, mLimitOverInterpolation); container.addChild(&matLimitOverInterpolation); + SimpleFieldChunk matClearCoatIorChange( + ChunkType::MaterialClearCoatIorChange, mClearCoatIorChange); + container.addChild(&matClearCoatIorChange); + SimpleFieldChunk matTransparency(ChunkType::MaterialTransparencyMode, static_cast(mTransparencyMode)); container.addChild(&matTransparency); diff --git a/libs/filamat/src/shaders/MaterialInfo.h b/libs/filamat/src/shaders/MaterialInfo.h index 4e53278586..957b6c132f 100644 --- a/libs/filamat/src/shaders/MaterialInfo.h +++ b/libs/filamat/src/shaders/MaterialInfo.h @@ -39,6 +39,7 @@ struct UTILS_PUBLIC MaterialInfo { bool hasShadowMultiplier; bool curvatureToRoughness; bool limitOverInterpolation; + bool clearCoatIorChange; bool flipUV; filament::AttributeBitset requiredAttributes; filament::BlendingMode blendingMode; diff --git a/libs/filamat/src/shaders/ShaderGenerator.cpp b/libs/filamat/src/shaders/ShaderGenerator.cpp index 693ccdf4e0..53d6a817c7 100644 --- a/libs/filamat/src/shaders/ShaderGenerator.cpp +++ b/libs/filamat/src/shaders/ShaderGenerator.cpp @@ -249,6 +249,8 @@ const std::string ShaderGenerator::createFragmentProgram(filament::driver::Shade cg.generateDefine(fs, "GEOMETRIC_SPECULAR_AA_ROUGHNESS", material.curvatureToRoughness); cg.generateDefine(fs, "GEOMETRIC_SPECULAR_AA_NORMAL", material.limitOverInterpolation); + cg.generateDefine(fs, "CLEAR_COAT_IOR_CHANGE", material.clearCoatIorChange); + // lighting variants bool litVariants = lit || material.hasShadowMultiplier; cg.generateDefine(fs, "HAS_DIRECTIONAL_LIGHTING", litVariants && variant.hasDirectionalLighting()); diff --git a/shaders/src/shading_lit.fs b/shaders/src/shading_lit.fs index bd932c4aff..4d04c523b4 100644 --- a/shaders/src/shading_lit.fs +++ b/shaders/src/shading_lit.fs @@ -68,11 +68,13 @@ void getPixelParams(const MaterialInputs material, out PixelParams pixel) { // Remap the roughness to perceptually linear roughness pixel.clearCoatRoughness = clearCoatRoughness; pixel.clearCoatLinearRoughness = clearCoatRoughness * clearCoatRoughness; +#if defined(CLEAR_COAT_IOR_CHANGE) // The base layer's f0 is computed assuming an interface from air to an IOR // of 1.5, but the clear coat layer forms an interface from IOR 1.5 to IOR // 1.5. We recompute f0 by first computing its IOR, then reconverting to f0 // by using the correct interface pixel.f0 = mix(pixel.f0, f0ClearCoatToSurface(pixel.f0), pixel.clearCoat); +#endif #if defined(MATERIAL_HAS_CLEAR_COAT_ROUGHNESS) // This is a hack but it will do: the base layer must be at least as rough diff --git a/tools/matc/src/matc/ParametersProcessor.cpp b/tools/matc/src/matc/ParametersProcessor.cpp index d4cfdb9362..424ee6b529 100644 --- a/tools/matc/src/matc/ParametersProcessor.cpp +++ b/tools/matc/src/matc/ParametersProcessor.cpp @@ -48,6 +48,7 @@ static constexpr const char* PARAM_KEY_SHADING = "shadingModel" static constexpr const char* PARAM_KEY_VARIANT_FILTER = "variantFilter"; static constexpr const char* PARAM_KEY_CURVATURE_TO_ROUGHNESS = "curvatureToRoughness"; static constexpr const char* PARAM_KEY_LIMIT_OVER_INTERPOLATION = "limitOverInterpolation"; +static constexpr const char* PARAM_KEY_CLEAR_COAT_IOR_CHANGE = "clearCoatIorChange"; static constexpr const char* PARAM_KEY_FLIP_UV = "flipUV"; ParametersProcessor::ParametersProcessor() { @@ -72,6 +73,8 @@ ParametersProcessor::ParametersProcessor() { = &ParametersProcessor::processCurvatureToRoughness; mConfigProcessor[PARAM_KEY_LIMIT_OVER_INTERPOLATION] = &ParametersProcessor::processLimitOverInterpolation; + mConfigProcessor[PARAM_KEY_CLEAR_COAT_IOR_CHANGE] + = &ParametersProcessor::processClearCoatIorChange; mConfigProcessor[PARAM_KEY_FLIP_UV] = &ParametersProcessor::processFlipUV; mRootAsserts[PARAM_KEY_NAME] = JsonishValue::Type::STRING; @@ -93,6 +96,7 @@ ParametersProcessor::ParametersProcessor() { mRootAsserts[PARAM_KEY_VARIANT_FILTER] = JsonishValue::Type::ARRAY; mRootAsserts[PARAM_KEY_CURVATURE_TO_ROUGHNESS] = JsonishValue::Type::BOOL; mRootAsserts[PARAM_KEY_LIMIT_OVER_INTERPOLATION] = JsonishValue::Type::BOOL; + mRootAsserts[PARAM_KEY_CLEAR_COAT_IOR_CHANGE] = JsonishValue::Type::BOOL; mRootAsserts[PARAM_KEY_FLIP_UV] = JsonishValue::Type::BOOL; mStringToInterpolation["smooth"] = MaterialBuilder::Interpolation::SMOOTH; @@ -464,7 +468,14 @@ bool ParametersProcessor::processLimitOverInterpolation(filamat::MaterialBuilder return true; } -bool ParametersProcessor::processFlipUV(filamat::MaterialBuilder& builder, const JsonishValue& value) { +bool ParametersProcessor::processClearCoatIorChange(filamat::MaterialBuilder& builder, + const JsonishValue& value) { + builder.clearCoatIorChange(value.toJsonBool()->getBool()); + return true; +} + +bool ParametersProcessor::processFlipUV(filamat::MaterialBuilder& builder, + const JsonishValue& value) { builder.flipUV(value.toJsonBool()->getBool()); return true; } diff --git a/tools/matc/src/matc/ParametersProcessor.h b/tools/matc/src/matc/ParametersProcessor.h index 9de775ed0f..b0c0874a9d 100644 --- a/tools/matc/src/matc/ParametersProcessor.h +++ b/tools/matc/src/matc/ParametersProcessor.h @@ -53,6 +53,7 @@ private: bool processShadowMultiplier(filamat::MaterialBuilder &builder, const JsonishValue &value); bool processCurvatureToRoughness(filamat::MaterialBuilder &builder, const JsonishValue &value); bool processLimitOverInterpolation(filamat::MaterialBuilder &builder, const JsonishValue &value); + bool processClearCoatIorChange(filamat::MaterialBuilder &builder, const JsonishValue &value); bool processFlipUV(filamat::MaterialBuilder &builder, const JsonishValue &value); bool processShading(filamat::MaterialBuilder &builder, const JsonishValue &value); bool processVariantFilter(filamat::MaterialBuilder &builder, const JsonishValue &value); diff --git a/tools/matinfo/src/main.cpp b/tools/matinfo/src/main.cpp index 5713e21183..f8a50ed556 100644 --- a/tools/matinfo/src/main.cpp +++ b/tools/matinfo/src/main.cpp @@ -380,6 +380,7 @@ static bool printMaterial(const ChunkContainer& container) { printChunk(container, filamat::MaterialShadowMultiplier, "Shadow multiply: "); printChunk(container, filamat::MaterialCurvatureToRoughness, "Curvature to roughness: "); printChunk(container, filamat::MaterialLimitOverInterpolation, "Limit interpolation: "); + printChunk(container, filamat::MaterialClearCoatIorChange, "Clear coat IOR change: "); std::cout << std::endl;