// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #pragma once #include "MaterialInfo.h" struct MaterialParamsLink; class GPUShader; class GPUContext; class GPUTextureView; class GPUConstantBuffer; class RenderBuffers; class SceneRenderTask; struct RenderView; struct RenderContext; struct DrawCall; /// /// Interface for material objects. /// class FLAXENGINE_API IMaterial { public: /// /// Gets the material info, structure which describes material surface. /// /// The constant reference to the material descriptor. virtual const MaterialInfo& GetInfo() const = 0; /// /// Gets the shader resource. /// /// The material shader resource. virtual GPUShader* GetShader() const = 0; /// /// Determines whether material is a surface shader. /// FORCE_INLINE bool IsSurface() const { return GetInfo().Domain == MaterialDomain::Surface; } /// /// Determines whether material is a post fx. /// FORCE_INLINE bool IsPostFx() const { return GetInfo().Domain == MaterialDomain::PostProcess; } /// /// Determines whether material is a decal. /// FORCE_INLINE bool IsDecal() const { return GetInfo().Domain == MaterialDomain::Decal; } /// /// Determines whether material is a GUI shader. /// FORCE_INLINE bool IsGUI() const { return GetInfo().Domain == MaterialDomain::GUI; } /// /// Determines whether material is a terrain shader. /// FORCE_INLINE bool IsTerrain() const { return GetInfo().Domain == MaterialDomain::Terrain; } /// /// Determines whether material is a particle shader. /// FORCE_INLINE bool IsParticle() const { return GetInfo().Domain == MaterialDomain::Particle; } /// /// Determines whether material is a deformable shader. /// FORCE_INLINE bool IsDeformable() const { return GetInfo().Domain == MaterialDomain::Deformable; } /// /// Returns true if material is ready for rendering. /// /// True if can render that material virtual bool IsReady() const = 0; /// /// Gets the mask of render passes supported by this material. /// /// The draw passes supported by this material. virtual DrawPass GetDrawModes() const { return DrawPass::None; } /// /// Returns true if material can use lightmaps (this includes lightmaps offline baking and sampling at runtime). /// /// True if can use lightmaps, otherwise false virtual bool CanUseLightmap() const { return false; } /// /// The instancing handling used to hash, batch and write draw calls. /// struct InstancingHandler { void (*GetHash)(const DrawCall& drawCall, uint32& batchKey); bool (*CanBatch)(const DrawCall& a, const DrawCall& b); void (*WriteDrawCall)(struct InstanceData* instanceData, const DrawCall& drawCall); }; /// /// Returns true if material can use draw calls instancing. /// /// The output data for the instancing handling used to hash, batch and write draw calls. Valid only when function returns true. /// True if can use instancing, otherwise false. virtual bool CanUseInstancing(InstancingHandler& handler) const { #if BUILD_DEBUG handler = { nullptr, nullptr, nullptr }; #endif return false; } public: /// /// Settings for the material binding to the graphics pipeline. /// struct BindParameters { GPUContext* GPUContext; const RenderContext& RenderContext; const DrawCall* FirstDrawCall; int32 DrawCallsCount; MaterialParamsLink* ParamsLink = nullptr; void* CustomData = nullptr; float TimeParam; /// /// The input scene color. It's optional and used in forward/postFx rendering. /// GPUTextureView* Input = nullptr; BindParameters(::GPUContext* context, const ::RenderContext& renderContext); BindParameters(::GPUContext* context, const ::RenderContext& renderContext, const DrawCall& drawCall); BindParameters(::GPUContext* context, const ::RenderContext& renderContext, const DrawCall* firstDrawCall, int32 drawCallsCount); // Per-view shared constant buffer (see ViewData in MaterialCommon.hlsl). static GPUConstantBuffer* PerViewConstants; // Binds the shared per-view constant buffer at slot 1 (see ViewData in MaterialCommon.hlsl) void BindViewData(); }; /// /// Binds the material state to the GPU pipeline. Should be called before the draw command. /// /// The material bind settings. virtual void Bind(BindParameters& params) = 0; };