diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 2c9c77e23a..f237c6ecf5 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -5,6 +5,8 @@ A new header is inserted each time a *tag* is created. ## Next release +- MaterialInstances now have optional names. + ## v1.6.0 - gltfio: fixed incorrect cone angles with lights. diff --git a/android/filament-android/src/main/cpp/Material.cpp b/android/filament-android/src/main/cpp/Material.cpp index 6fda58f1b6..beb9b51a2f 100644 --- a/android/filament-android/src/main/cpp/Material.cpp +++ b/android/filament-android/src/main/cpp/Material.cpp @@ -47,6 +47,16 @@ Java_com_google_android_filament_Material_nCreateInstance(JNIEnv*, jclass, return (jlong) material->createInstance(); } +extern "C" JNIEXPORT jlong JNICALL +Java_com_google_android_filament_Material_nCreateInstanceWithName(JNIEnv* env, jclass, + jlong nativeMaterial, jstring name_) { + Material* material = (Material*) nativeMaterial; + const char *name = env->GetStringUTFChars(name_, 0); + jlong instance = (jlong) material->createInstance(name); + env->ReleaseStringUTFChars(name_, name); + return instance; +} + extern "C" JNIEXPORT jstring JNICALL Java_com_google_android_filament_Material_nGetName(JNIEnv* env, jclass, jlong nativeMaterial) { diff --git a/android/filament-android/src/main/java/com/google/android/filament/Material.java b/android/filament-android/src/main/java/com/google/android/filament/Material.java index b82e4c8309..eb0343ae27 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/Material.java +++ b/android/filament-android/src/main/java/com/google/android/filament/Material.java @@ -326,6 +326,21 @@ public class Material { return new MaterialInstance(this, nativeInstance); } + /** + * Creates a new instance of this material with a specified name. Material instances should be + * freed using {@link Engine#destroyMaterialInstance(MaterialInstance)}. + * + * @param name arbitrary label to associate with the given material instance + * + * @return the new instance + */ + @NonNull + public MaterialInstance createInstance(@NonNull String name) { + long nativeInstance = nCreateInstanceWithName(getNativeObject(), name); + if (nativeInstance == 0) throw new IllegalStateException("Couldn't create MaterialInstance"); + return new MaterialInstance(this, nativeInstance, name); + } + /** Returns the material's default instance. */ @NonNull public MaterialInstance getDefaultInstance() { @@ -879,6 +894,7 @@ public class Material { private static native long nBuilderBuild(long nativeEngine, @NonNull Buffer buffer, int size); private static native long nCreateInstance(long nativeMaterial); + private static native long nCreateInstanceWithName(long nativeMaterial, @NonNull String name); private static native long nGetDefaultInstance(long nativeMaterial); private static native String nGetName(long nativeMaterial); diff --git a/android/filament-android/src/main/java/com/google/android/filament/MaterialInstance.java b/android/filament-android/src/main/java/com/google/android/filament/MaterialInstance.java index d82b4714ba..c93f5fa18f 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/MaterialInstance.java +++ b/android/filament-android/src/main/java/com/google/android/filament/MaterialInstance.java @@ -24,6 +24,7 @@ public class MaterialInstance { private Material mMaterial; private long mNativeObject; private long mNativeMaterial; + private String mName; public enum BooleanElement { BOOL, @@ -53,6 +54,12 @@ public class MaterialInstance { mNativeObject = nativeMaterialInstance; } + MaterialInstance(@NonNull Material material, long nativeMaterialInstance, String name) { + mMaterial = material; + mNativeObject = nativeMaterialInstance; + mName = name; + } + MaterialInstance(long nativeMaterial, long nativeMaterialInstance) { mNativeMaterial = nativeMaterial; mNativeObject = nativeMaterialInstance; @@ -67,6 +74,11 @@ public class MaterialInstance { return mMaterial; } + /** @return the name associated with this instance if one exists, otherwise null */ + public String getName() { + return mName; + } + /** * Sets the value of a bool parameter. * diff --git a/filament/include/filament/Material.h b/filament/include/filament/Material.h index 6be3a8df13..6fce86359a 100644 --- a/filament/include/filament/Material.h +++ b/filament/include/filament/Material.h @@ -123,9 +123,12 @@ public: * Creates a new instance of this material. Material instances should be freed using * Engine::destroy(const MaterialInstance*). * + * @param name Optional name to associate with the given material instance. If this is null, + * then there is no associated name (note that the material's name does not get inherited). + * * @return A pointer to the new instance. */ - MaterialInstance* createInstance() const noexcept; + MaterialInstance* createInstance(const char* name = nullptr) const noexcept; //! Returns the name of this material as a null-terminated string. const char* getName() const noexcept; diff --git a/filament/include/filament/MaterialInstance.h b/filament/include/filament/MaterialInstance.h index bbc867b22d..8a617316a7 100644 --- a/filament/include/filament/MaterialInstance.h +++ b/filament/include/filament/MaterialInstance.h @@ -65,6 +65,11 @@ public: */ Material const* getMaterial() const noexcept; + /** + * @return the name associated with this instance if one exists, otherwise null + */ + const char* getName() const noexcept; + /** * Set a uniform by name * diff --git a/filament/src/Engine.cpp b/filament/src/Engine.cpp index 61377664af..99ef2f331c 100644 --- a/filament/src/Engine.cpp +++ b/filament/src/Engine.cpp @@ -551,8 +551,9 @@ FRenderer* FEngine::createRenderer() noexcept { return p; } -FMaterialInstance* FEngine::createMaterialInstance(const FMaterial* material) noexcept { - FMaterialInstance* p = mHeapAllocator.make(*this, material); +FMaterialInstance* FEngine::createMaterialInstance(const FMaterial* material, + const char* name) noexcept { + FMaterialInstance* p = mHeapAllocator.make(*this, material, name); if (p) { auto pos = mMaterialInstances.emplace(material, "MaterialInstance"); pos.first->second.insert(p); diff --git a/filament/src/Material.cpp b/filament/src/Material.cpp index 3969d51b1c..183d306e61 100644 --- a/filament/src/Material.cpp +++ b/filament/src/Material.cpp @@ -286,8 +286,8 @@ void FMaterial::terminate(FEngine& engine) { mDefaultInstance.terminate(engine); } -FMaterialInstance* FMaterial::createInstance() const noexcept { - return mEngine.createMaterialInstance(this); +FMaterialInstance* FMaterial::createInstance(const char* name) const noexcept { + return mEngine.createMaterialInstance(this, name); } bool FMaterial::hasParameter(const char* name) const noexcept { @@ -529,8 +529,8 @@ void FMaterial::destroyPrograms(FEngine& engine) { using namespace details; -MaterialInstance* Material::createInstance() const noexcept { - return upcast(this)->createInstance(); +MaterialInstance* Material::createInstance(const char* name) const noexcept { + return upcast(this)->createInstance(name); } const char* Material::getName() const noexcept { diff --git a/filament/src/MaterialInstance.cpp b/filament/src/MaterialInstance.cpp index 3737493e36..977c6d4609 100644 --- a/filament/src/MaterialInstance.cpp +++ b/filament/src/MaterialInstance.cpp @@ -41,7 +41,8 @@ namespace details { FMaterialInstance::FMaterialInstance() noexcept = default; -FMaterialInstance::FMaterialInstance(FEngine& engine, FMaterial const* material) { +FMaterialInstance::FMaterialInstance(FEngine& engine, FMaterial const* material, const char* name) : + mName(name) { FEngine::DriverApi& driver = engine.getDriverApi(); if (!material->getUniformInterfaceBlock().isEmpty()) { @@ -223,7 +224,11 @@ template UTILS_NOINLINE void FMaterialInstance::setParameter (const cha using namespace details; Material const* MaterialInstance::getMaterial() const noexcept { - return upcast(this)->mMaterial; + return upcast(this)->getMaterial(); +} + +const char* MaterialInstance::getName() const noexcept { + return upcast(this)->getName(); } template diff --git a/filament/src/Skybox.cpp b/filament/src/Skybox.cpp index 3da96519c6..df9215ae01 100644 --- a/filament/src/Skybox.cpp +++ b/filament/src/Skybox.cpp @@ -98,7 +98,7 @@ FSkybox::FSkybox(FEngine& engine, const Builder& builder) noexcept mIntensity(builder->mIntensity) { FMaterial const* material = engine.getSkyboxMaterial(); - mSkyboxMaterialInstance = material->createInstance(); + mSkyboxMaterialInstance = material->createInstance("Skybox"); TextureSampler sampler(TextureSampler::MagFilter::LINEAR, TextureSampler::WrapMode::REPEAT); auto pInstance = static_cast(mSkyboxMaterialInstance); diff --git a/filament/src/details/Engine.h b/filament/src/details/Engine.h index 2e1cc1da0e..81fce37ef5 100644 --- a/filament/src/details/Engine.h +++ b/filament/src/details/Engine.h @@ -230,7 +230,7 @@ public: void createLight(const LightManager::Builder& builder, utils::Entity entity); FRenderer* createRenderer() noexcept; - FMaterialInstance* createMaterialInstance(const FMaterial* material) noexcept; + FMaterialInstance* createMaterialInstance(const FMaterial* material, const char* name) noexcept; FScene* createScene() noexcept; FView* createView() noexcept; diff --git a/filament/src/details/Material.h b/filament/src/details/Material.h index 1d9d53ea22..63789224c2 100644 --- a/filament/src/details/Material.h +++ b/filament/src/details/Material.h @@ -65,7 +65,7 @@ public: } // Create an instance of this material - FMaterialInstance* createInstance() const noexcept; + FMaterialInstance* createInstance(const char* name) const noexcept; bool hasParameter(const char* name) const noexcept; diff --git a/filament/src/details/MaterialInstance.h b/filament/src/details/MaterialInstance.h index 0fb0d62c1f..852cf31656 100644 --- a/filament/src/details/MaterialInstance.h +++ b/filament/src/details/MaterialInstance.h @@ -38,7 +38,7 @@ class FMaterial; class FMaterialInstance : public MaterialInstance { public: - FMaterialInstance(FEngine& engine, FMaterial const* material); + FMaterialInstance(FEngine& engine, FMaterial const* material, const char* name); FMaterialInstance(const FMaterialInstance& rhs) = delete; FMaterialInstance& operator=(const FMaterialInstance& rhs) = delete; @@ -132,6 +132,8 @@ public: void setDepthCulling(bool enable) noexcept; + const char* getName() const noexcept { return mName.c_str(); } + private: friend class FMaterial; friend class MaterialInstance; @@ -162,6 +164,8 @@ private: (uint32_t)std::numeric_limits::max(), (uint32_t)std::numeric_limits::max() }; + + utils::CString mName; }; FILAMENT_UPCAST(MaterialInstance) diff --git a/web/filament-js/filament.d.ts b/web/filament-js/filament.d.ts index 76bcc4ce15..459dbf590f 100644 --- a/web/filament-js/filament.d.ts +++ b/web/filament-js/filament.d.ts @@ -109,6 +109,7 @@ export class TextureSampler { } export class MaterialInstance { + public getName(): string; public setBoolParameter(name: string, value: boolean): void; public setFloatParameter(name: string, value: number): void; public setFloat2Parameter(name: string, value: float2): void; @@ -283,6 +284,7 @@ export class Renderer { export class Material { public createInstance(): MaterialInstance; + public createNamedInstance(name: string): MaterialInstance; public getDefaultInstance(): MaterialInstance; public getName(): string; } diff --git a/web/filament-js/jsbindings.cpp b/web/filament-js/jsbindings.cpp index d7f4deb044..79ed13b7da 100644 --- a/web/filament-js/jsbindings.cpp +++ b/web/filament-js/jsbindings.cpp @@ -988,11 +988,18 @@ class_("Material") select_overload(&Material::getDefaultInstance), allow_raw_pointers()) .function("createInstance", &Material::createInstance, allow_raw_pointers()) + .function("createNamedInstance", EMBIND_LAMBDA(MaterialInstance*, + (Material* self, std::string name), { + return self->createInstance(name.c_str()); }), allow_raw_pointers()) .function("getName", EMBIND_LAMBDA(std::string, (Material* self), { return std::string(self->getName()); }), allow_raw_pointers()); class_("MaterialInstance") + .function("getName", EMBIND_LAMBDA(std::string, (MaterialInstance* self), { + const char* name = self->getName(); + return std::string(name ? name : ""); + }), allow_raw_pointers()) .function("setBoolParameter", EMBIND_LAMBDA(void, (MaterialInstance* self, std::string name, bool value), { self->setParameter(name.c_str(), value); }), allow_raw_pointers())