/* * 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 TNT_FILAMENT_MATERIAL_H #define TNT_FILAMENT_MATERIAL_H #include #include #include #include #include #include #include #include #include #include namespace utils { class CString; } // namespace utils namespace filament { class Texture; class TextureSampler; class FEngine; class FMaterial; class Engine; class UTILS_PUBLIC Material : public FilamentAPI { struct BuilderDetails; public: using BlendingMode = BlendingMode; using Shading = Shading; using Interpolation = Interpolation; using VertexDomain = VertexDomain; using TransparencyMode = TransparencyMode; using ParameterType = backend::UniformType; using Precision = backend::Precision; using SamplerType = backend::SamplerType; using SamplerFormat = backend::SamplerFormat; using CullingMode = backend::CullingMode; using ShaderModel = backend::ShaderModel; using SubpassType = backend::SubpassType; /** * Holds information about a material parameter. */ struct ParameterInfo { //! Name of the parameter. const char* name; //! Whether the parameter is a sampler (texture). bool isSampler; //! Whether the parameter is a subpass type. bool isSubpass; union { //! Type of the parameter if the parameter is not a sampler. ParameterType type; //! Type of the parameter if the parameter is a sampler. SamplerType samplerType; //! Type of the parameter if the parameter is a subpass. SubpassType subpassType; }; //! Size of the parameter when the parameter is an array. uint32_t count; //! Requested precision of the parameter. Precision precision; }; class Builder : public BuilderBase { friend struct BuilderDetails; public: Builder() noexcept; Builder(Builder const& rhs) noexcept; Builder(Builder&& rhs) noexcept; ~Builder() noexcept; Builder& operator=(Builder const& rhs) noexcept; Builder& operator=(Builder&& rhs) noexcept; /** * Specifies the material data. The material data is a binary blob produced by * libfilamat or by matc. * * @param payload Pointer to the material data, must stay valid until build() is called. * @param size Size of the material data pointed to by "payload" in bytes. */ Builder& package(const void* payload, size_t size); template using is_supported_constant_parameter_t = typename std::enable_if< std::is_same::value || std::is_same::value || std::is_same::value>::type; /** * Specialize a constant parameter specified in the material definition with a concrete * value for this material. Once build() is called, this constant cannot be changed. * Will throw an exception if the name does not match a constant specified in the * material definition or if the type provided does not match. * * @tparam T The type of constant parameter, either int32_t, float, or bool. * @param name The name of the constant parameter specified in the material definition, such * as "myConstant". * @param nameLength Length in `char` of the name parameter. * @param value The value to use for the constant parameter, must match the type specified * in the material definition. */ template> Builder& constant(const char* name, size_t nameLength, T value); /** inline helper to provide the constant name as a null-terminated C string */ template> inline Builder& constant(const char* name, T value) { return constant(name, strlen(name), value); } /** * Creates the Material object and returns a pointer to it. * * @param engine Reference to the filament::Engine to associate this Material with. * * @return pointer to the newly created object or nullptr if exceptions are disabled and * an error occurred. * * @exception utils::PostConditionPanic if a runtime error occurred, such as running out of * memory or other resources. * @exception utils::PreConditionPanic if a parameter to a builder function was invalid. */ Material* build(Engine& engine); private: friend class FMaterial; }; using CompilerPriorityQueue = backend:: CompilerPriorityQueue; /** * Asynchronously ensures that a subset of this Material's variants are compiled. After issuing * several Material::compile() calls in a row, it is recommended to call Engine::flush() * such that the backend can start the compilation work as soon as possible. * The provided callback is guaranteed to be called on the main thread after all specified * variants of the material are compiled. This can take hundreds of milliseconds. * * If all the material's variants are already compiled, the callback will be scheduled as * soon as possible, but this might take a few dozen millisecond, corresponding to how * many previous frames are enqueued in the backend. This also varies by backend. Therefore, * it is recommended to only call this method once per material shortly after creation. * * If the same variant is scheduled for compilation multiple times, the first scheduling * takes precedence; later scheduling are ignored. * * caveat: A consequence is that if a variant is scheduled on the low priority queue and later * scheduled again on the high priority queue, the later scheduling is ignored. * Therefore, the second callback could be called before the variant is compiled. * However, the first callback, if specified, will trigger as expected. * * The callback is guaranteed to be called. If the engine is destroyed while some material * variants are still compiling or in the queue, these will be discarded and the corresponding * callback will be called. In that case however the Material pointer passed to the callback * is guaranteed to be invalid (either because it's been destroyed by the user already, or, * because it's been cleaned-up by the Engine). * * UserVariantFilterMask::ALL should be used with caution. Only variants that an application * needs should be included in the variants argument. For example, the STE variant is only used * for stereoscopic rendering. If an application is not planning to render in stereo, this bit * should be turned off to avoid unnecessary material compilations. * * @param priority Which priority queue to use, LOW or HIGH. * @param variants Variants to include to the compile command. * @param handler Handler to dispatch the callback or nullptr for the default handler * @param callback callback called on the main thread when the compilation is done on * by backend. */ void compile(CompilerPriorityQueue priority, UserVariantFilterMask variants, backend::CallbackHandler* handler = nullptr, utils::Invocable&& callback = {}) noexcept; inline void compile(CompilerPriorityQueue priority, UserVariantFilterBit variants, backend::CallbackHandler* handler = nullptr, utils::Invocable&& callback = {}) noexcept { compile(priority, UserVariantFilterMask(variants), handler, std::forward>(callback)); } inline void compile(CompilerPriorityQueue priority, backend::CallbackHandler* handler = nullptr, utils::Invocable&& callback = {}) noexcept { compile(priority, UserVariantFilterBit::ALL, handler, std::forward>(callback)); } /** * 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 the instance inherits the material's name. * * @return A pointer to the new instance. */ MaterialInstance* createInstance(const char* name = nullptr) const noexcept; //! Returns the name of this material as a null-terminated string. const char* getName() const noexcept; //! Returns the shading model of this material. Shading getShading() const noexcept; //! Returns the interpolation mode of this material. This affects how variables are interpolated. Interpolation getInterpolation() const noexcept; //! Returns the blending mode of this material. BlendingMode getBlendingMode() const noexcept; //! Returns the vertex domain of this material. VertexDomain getVertexDomain() const noexcept; //! Returns the material domain of this material. //! The material domain determines how the material is used. MaterialDomain getMaterialDomain() const noexcept; //! Returns the default culling mode of this material. CullingMode getCullingMode() const noexcept; //! Returns the transparency mode of this material. //! This value only makes sense when the blending mode is transparent or fade. TransparencyMode getTransparencyMode() const noexcept; //! Indicates whether instances of this material will, by default, write to the color buffer. bool isColorWriteEnabled() const noexcept; //! Indicates whether instances of this material will, by default, write to the depth buffer. bool isDepthWriteEnabled() const noexcept; //! Indicates whether instances of this material will, by default, use depth testing. bool isDepthCullingEnabled() const noexcept; //! Indicates whether this material is double-sided. bool isDoubleSided() const noexcept; //! Indicates whether this material uses alpha to coverage. bool isAlphaToCoverageEnabled() const noexcept; //! Returns the alpha mask threshold used when the blending mode is set to masked. float getMaskThreshold() const noexcept; //! Indicates whether this material uses the shadowing factor as a color multiplier. //! This values only makes sense when the shading mode is unlit. bool hasShadowMultiplier() const noexcept; //! Indicates whether this material has specular anti-aliasing enabled bool hasSpecularAntiAliasing() const noexcept; //! Returns the screen-space variance for specular-antialiasing, this value is between 0 and 1. float getSpecularAntiAliasingVariance() const noexcept; //! Returns the clamping threshold for specular-antialiasing, this value is between 0 and 1. float getSpecularAntiAliasingThreshold() const noexcept; //! Returns the list of vertex attributes required by this material. AttributeBitset getRequiredAttributes() const noexcept; //! Returns the refraction mode used by this material. RefractionMode getRefractionMode() const noexcept; //! Return the refraction type used by this material. RefractionType getRefractionType() const noexcept; //! Returns the reflection mode used by this material. ReflectionMode getReflectionMode() const noexcept; /** * Returns the number of parameters declared by this material. * The returned value can be 0. */ size_t getParameterCount() const noexcept; /** * Gets information about this material's parameters. * * @param parameters A pointer to a list of ParameterInfo. * The list must be at least "count" large * @param count The number of parameters to retrieve. Must be >= 0 and can be > count. * * @return The number of parameters written to the parameters pointer. */ size_t getParameters(ParameterInfo* parameters, size_t count) const noexcept; //! Indicates whether a parameter of the given name exists on this material. bool hasParameter(const char* name) const noexcept; //! Indicates whether an existing parameter is a sampler or not. bool isSampler(const char* name) const noexcept; /** * Sets the value of the given parameter on this material's default instance. * * @param name The name of the material parameter * @param value The value of the material parameter * * @see getDefaultInstance() */ template void setDefaultParameter(const char* name, T value) noexcept { getDefaultInstance()->setParameter(name, value); } /** * Sets a texture and sampler parameters on this material's default instance. * * @param name The name of the material texture parameter * @param texture The texture to set as parameter * @param sampler The sampler to be used with this texture * * @see getDefaultInstance() */ void setDefaultParameter(const char* name, Texture const* texture, TextureSampler const& sampler) noexcept { getDefaultInstance()->setParameter(name, texture, sampler); } /** * Sets the color of the given parameter on this material's default instance. * * @param name The name of the material color parameter * @param type Whether the color is specified in the linear or sRGB space * @param color The color as a floating point red, green, blue tuple * * @see getDefaultInstance() */ void setDefaultParameter(const char* name, RgbType type, math::float3 color) noexcept { getDefaultInstance()->setParameter(name, type, color); } /** * Sets the color of the given parameter on this material's default instance. * * @param name The name of the material color parameter * @param type Whether the color is specified in the linear or sRGB space * @param color The color as a floating point red, green, blue, alpha tuple * * @see getDefaultInstance() */ void setDefaultParameter(const char* name, RgbaType type, math::float4 color) noexcept { getDefaultInstance()->setParameter(name, type, color); } //! Returns this material's default instance. MaterialInstance* getDefaultInstance() noexcept; //! Returns this material's default instance. MaterialInstance const* getDefaultInstance() const noexcept; }; } // namespace filament #endif // TNT_FILAMENT_MATERIAL_H