Add clearCoatIorChange property to materials (#890)
This property can be used to control the darkening of the base layer due to a change in index of refraction when going through the clear coat layer.
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
BIN
docs/images/screenshot_clear_coat_ior_change.jpg
Normal file
BIN
docs/images/screenshot_clear_coat_ior_change.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
BIN
docs/images/screenshot_curvature_to_roughness.jpg
Normal file
BIN
docs/images/screenshot_curvature_to_roughness.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 152 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 346 KiB |
@@ -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"),
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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<bool> matClearCoatIorChange(
|
||||
ChunkType::MaterialClearCoatIorChange, mClearCoatIorChange);
|
||||
container.addChild(&matClearCoatIorChange);
|
||||
|
||||
SimpleFieldChunk<uint8_t> matTransparency(ChunkType::MaterialTransparencyMode,
|
||||
static_cast<uint8_t>(mTransparencyMode));
|
||||
container.addChild(&matTransparency);
|
||||
|
||||
@@ -39,6 +39,7 @@ struct UTILS_PUBLIC MaterialInfo {
|
||||
bool hasShadowMultiplier;
|
||||
bool curvatureToRoughness;
|
||||
bool limitOverInterpolation;
|
||||
bool clearCoatIorChange;
|
||||
bool flipUV;
|
||||
filament::AttributeBitset requiredAttributes;
|
||||
filament::BlendingMode blendingMode;
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -380,6 +380,7 @@ static bool printMaterial(const ChunkContainer& container) {
|
||||
printChunk<bool, bool>(container, filamat::MaterialShadowMultiplier, "Shadow multiply: ");
|
||||
printChunk<bool, bool>(container, filamat::MaterialCurvatureToRoughness, "Curvature to roughness: ");
|
||||
printChunk<bool, bool>(container, filamat::MaterialLimitOverInterpolation, "Limit interpolation: ");
|
||||
printChunk<bool, bool>(container, filamat::MaterialClearCoatIorChange, "Clear coat IOR change: ");
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user