// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #pragma once #include "../Enums.h" #include "Engine/Core/Math/Math.h" /// /// Material domain type. Material domain defines the target usage of the material shader. /// API_ENUM() enum class MaterialDomain : byte { /// /// The surface material. Can be used to render the scene geometry including models and skinned models. /// Surface = 0, /// /// The post process material. Can be used to perform custom post-processing of the rendered frame. /// PostProcess = 1, /// /// The deferred decal material. Can be used to apply custom overlay or surface modifications to the object surfaces in the world. /// Decal = 2, /// /// The GUI shader. Can be used to draw custom control interface elements or to add custom effects to the GUI. /// GUI = 3, /// /// The terrain shader. Can be used only with landscape chunks geometry that use optimized vertex data and support multi-layered blending. /// Terrain = 4, /// /// The particle shader. Can be used only with particles geometry (sprites, trails and ribbons). Supports reading particle data on a GPU. /// Particle = 5, }; /// /// Material blending modes. /// API_ENUM() enum class MaterialBlendMode : byte { /// /// The opaque material. Used during GBuffer pass rendering. /// Opaque = 0, /// /// The transparent material. Used during Forward pass rendering. /// Transparent = 1, /// /// The additive blend. Material color is used to add to color of the objects behind the surface. Used during Forward pass rendering. /// Additive = 2, /// /// The multiply blend. Material color is used to multiply color of the objects behind the surface. Used during Forward pass rendering. /// Multiply = 3, }; // Old material blending mode used before introducing MaterialShadingModel // [Deprecated on 10.09.2018, expires on 10.05.2019] enum class OldMaterialBlendMode : byte { Opaque = 0, Transparent = 1, Unlit = 2, }; /// /// Material shading modes. Defines how material inputs and properties are combined to result the final surface color. /// API_ENUM() enum class MaterialShadingModel : byte { /// /// The unlit material. Emissive channel is used as an output color. Can perform custom lighting operations or just glow. Won't be affected by the lighting pipeline. /// Unlit = 0, /// /// The default lit material. The most common choice for the material surfaces. /// Lit = 1, /// /// The subsurface material. Intended for materials like vax or skin that need light scattering to transport simulation through the object. /// Subsurface = 2, /// /// The foliage material. Intended for foliage materials like leaves and grass that need light scattering to transport simulation through the thin object. /// Foliage = 3, }; /// /// Material transparent lighting modes. /// [Deprecated on 24.07.2019, expires on 10.05.2021] /// enum class MaterialTransparentLighting_Deprecated : byte { /// /// Shading is disabled. /// None = 0, /// /// Shading is performed per pixel for single directional light. /// SingleDirectionalPerPixel = 1 }; /// /// Material usage flags (deprecated). /// [Deprecated on 24.07.2019, expires on 10.05.2021] /// enum class MaterialFlags_Deprecated : uint32 { /// /// The none. /// None = 0, /// /// Material is using mask to discard some pixels. /// Masked materials are using full vertex buffer during shadow maps and depth pass rendering (need UVs). /// UseMask = 1 << 0, /// /// The two sided material. No triangle normal culling is performed. /// TwoSided = 1 << 1, /// /// The wireframe material. /// Wireframe = 1 << 2, /// /// The material is using emissive light. /// UseEmissive = 1 << 3, /// /// The transparent materials option. Disable depth test (material ignores depth). /// TransparentDisableDepthTest = 1 << 4, /// /// The transparent materials option. Disable fog. /// TransparentDisableFog = 1 << 5, /// /// The transparent materials option. Disable reflections. /// TransparentDisableReflections = 1 << 6, /// /// The transparent materials option. Disable depth buffer write (won't modify depth buffer value after rendering). /// DisableDepthWrite = 1 << 7, /// /// The transparent materials option. Disable distortion. /// TransparentDisableDistortion = 1 << 8, /// /// The material is using world position offset (it may be animated inside a shader). /// UsePositionOffset = 1 << 9, /// /// The material is using vertex colors. The render will try to feed the pipeline with a proper buffer so material can gather valid data. /// UseVertexColor = 1 << 10, /// /// The material is using per-pixel normal mapping. /// UseNormal = 1 << 11, /// /// The material is using position displacement (in domain shader). /// UseDisplacement = 1 << 12, /// /// The flag used to indicate that material input normal vector is defined in the world space rather than tangent space. /// InputWorldSpaceNormal = 1 << 13, /// /// The flag used to indicate that material uses dithered model LOD transition for smoother LODs switching. /// UseDitheredLODTransition = 1 << 14, /// /// The flag used to indicate that material uses refraction feature. /// UseRefraction = 1 << 15, }; DECLARE_ENUM_OPERATORS(MaterialFlags_Deprecated); /// /// Material features flags. /// API_ENUM(Attributes="Flags") enum class MaterialFeaturesFlags : uint32 { /// /// No flags. /// None = 0, /// /// The wireframe material. /// Wireframe = 1 << 1, /// /// The depth test is disabled (material ignores depth). /// DisableDepthTest = 1 << 2, /// /// Disable depth buffer write (won't modify depth buffer value during rendering). /// DisableDepthWrite = 1 << 3, /// /// The flag used to indicate that material input normal vector is defined in the world space rather than tangent space. /// InputWorldSpaceNormal = 1 << 4, /// /// The flag used to indicate that material uses dithered model LOD transition for smoother LODs switching. /// DitheredLODTransition = 1 << 5, /// /// The flag used to disable fog. The Forward Pass materials option. /// DisableFog = 1 << 6, /// /// The flag used to disable reflections. The Forward Pass materials option. /// DisableReflections = 1 << 7, /// /// The flag used to disable distortion effect (light refraction). The Forward Pass materials option. /// DisableDistortion = 1 << 8, /// /// The flag used to enable refraction offset based on the difference between the per-pixel normal and the per-vertex normal. Useful for large water-like surfaces. /// PixelNormalOffsetRefraction = 1 << 9, }; DECLARE_ENUM_OPERATORS(MaterialFeaturesFlags); /// /// Material features usage flags. Detected by the material generator to help graphics pipeline optimize rendering of material shaders. /// API_ENUM(Attributes="Flags") enum class MaterialUsageFlags : uint32 { /// /// No flags. /// None = 0, /// /// Material is using mask to discard some pixels. Masked materials are using full vertex buffer during shadow maps and depth pass rendering (need UVs). /// UseMask = 1 << 0, /// /// The material is using emissive light. /// UseEmissive = 1 << 1, /// /// The material is using world position offset (it may be animated inside a shader). /// UsePositionOffset = 1 << 2, /// /// The material is using vertex colors. The render will try to feed the pipeline with a proper buffer so material can gather valid data. /// UseVertexColor = 1 << 3, /// /// The material is using per-pixel normal mapping. /// UseNormal = 1 << 4, /// /// The material is using position displacement (in domain shader). /// UseDisplacement = 1 << 5, /// /// The flag used to indicate that material uses refraction feature. /// UseRefraction = 1 << 6, }; DECLARE_ENUM_OPERATORS(MaterialUsageFlags); /// /// Decal material blending modes. /// API_ENUM() enum class MaterialDecalBlendingMode : byte { /// /// Decal will be fully blended with the material surface. /// Translucent = 0, /// /// Decal color will be blended with the material surface color (using multiplication). /// Stain = 1, /// /// Decal will blend the normal vector only. /// Normal = 2, /// /// Decal will apply the emissive light only. /// Emissive = 3, }; /// /// Material input scene textures. Special inputs from the graphics pipeline. /// API_ENUM() enum class MaterialSceneTextures { /// /// The scene color. /// SceneColor = 0, /// /// The scene depth. /// SceneDepth = 1, /// /// The material diffuse color. /// DiffuseColor = 2, /// /// The material specular color. /// SpecularColor = 3, /// /// The material world space normal. /// WorldNormal = 4, /// /// The ambient occlusion. /// AmbientOcclusion = 5, /// /// The material metalness value. /// Metalness = 6, /// /// The material roughness value. /// Roughness = 7, /// /// The material specular value. /// Specular = 8, /// /// The material color. /// BaseColor = 9, /// /// The material shading mode. /// ShadingModel = 10, }; /// /// Material info structure - version 1 /// [Deprecated on 10.09.2018, expires on 10.05.2019] /// struct MaterialInfo1 { int32 Version; MaterialDomain Domain; OldMaterialBlendMode BlendMode; MaterialFlags_Deprecated Flags; /// /// Compare structure with other one /// /// Other structure to compare /// True if both structures are equal bool operator==(const MaterialInfo1& other) const { return Domain == other.Domain && BlendMode == other.BlendMode && Flags == other.Flags; } }; /// /// Material info structure - version 2 /// [Deprecated on 10.09.2018, expires on 10.05.2019] /// struct MaterialInfo2 { int32 Version; MaterialDomain Domain; OldMaterialBlendMode BlendMode; MaterialFlags_Deprecated Flags; MaterialTransparentLighting_Deprecated TransparentLighting; /// /// Compare structure with other one /// /// Other structure to compare /// True if both structures are equal bool operator==(const MaterialInfo2& other) const { return Domain == other.Domain && BlendMode == other.BlendMode && TransparentLighting == other.TransparentLighting && Flags == other.Flags; } }; /// /// Material info structure - version 3 /// [Deprecated on 10.09.2018, expires on 10.05.2019] /// struct MaterialInfo3 { MaterialDomain Domain; OldMaterialBlendMode BlendMode; MaterialFlags_Deprecated Flags; MaterialTransparentLighting_Deprecated TransparentLighting; /// /// Compare structure with other one /// /// Other structure to compare /// True if both structures are equal bool operator==(const MaterialInfo3& other) const { return Domain == other.Domain && BlendMode == other.BlendMode && TransparentLighting == other.TransparentLighting && Flags == other.Flags; } }; /// /// Material info structure - version 4 /// [Deprecated on 10.09.2018, expires on 10.05.2019] /// struct MaterialInfo4 { MaterialDomain Domain; OldMaterialBlendMode BlendMode; MaterialFlags_Deprecated Flags; MaterialTransparentLighting_Deprecated TransparentLighting; MaterialPostFxLocation PostFxLocation; /// /// Compare structure with other one /// /// Other structure to compare /// True if both structures are equal bool operator==(const MaterialInfo4& other) const { return Domain == other.Domain && BlendMode == other.BlendMode && TransparentLighting == other.TransparentLighting && PostFxLocation == other.PostFxLocation && Flags == other.Flags; } }; /// /// Material info structure - version 5 /// [Deprecated on 10.09.2018, expires on 10.05.2019] /// struct MaterialInfo5 { MaterialDomain Domain; OldMaterialBlendMode BlendMode; MaterialFlags_Deprecated Flags; MaterialTransparentLighting_Deprecated TransparentLighting; MaterialPostFxLocation PostFxLocation; float MaskThreshold; float OpacityThreshold; /// /// Compare structure with other one /// /// Other structure to compare /// True if both structures are equal bool operator==(const MaterialInfo5& other) const { return Domain == other.Domain && BlendMode == other.BlendMode && TransparentLighting == other.TransparentLighting && PostFxLocation == other.PostFxLocation && Math::NearEqual(MaskThreshold, other.MaskThreshold) && Math::NearEqual(OpacityThreshold, other.OpacityThreshold) && Flags == other.Flags; } }; /// /// Material info structure - version 6 /// [Deprecated on 10.09.2018, expires on 10.05.2019] /// struct MaterialInfo6 { MaterialDomain Domain; OldMaterialBlendMode BlendMode; MaterialFlags_Deprecated Flags; MaterialTransparentLighting_Deprecated TransparentLighting; MaterialDecalBlendingMode DecalBlendingMode; MaterialPostFxLocation PostFxLocation; float MaskThreshold; float OpacityThreshold; MaterialInfo6() { } MaterialInfo6(const MaterialInfo5& other) { Domain = other.Domain; BlendMode = other.BlendMode; Flags = other.Flags; TransparentLighting = other.TransparentLighting; DecalBlendingMode = MaterialDecalBlendingMode::Translucent; PostFxLocation = other.PostFxLocation; MaskThreshold = other.MaskThreshold; OpacityThreshold = other.OpacityThreshold; } /// /// Compare structure with other one /// /// Other structure to compare /// True if both structures are equal bool operator==(const MaterialInfo6& other) const { return Domain == other.Domain && BlendMode == other.BlendMode && TransparentLighting == other.TransparentLighting && DecalBlendingMode == other.DecalBlendingMode && PostFxLocation == other.PostFxLocation && Math::NearEqual(MaskThreshold, other.MaskThreshold) && Math::NearEqual(OpacityThreshold, other.OpacityThreshold) && Flags == other.Flags; } }; /// /// Material info structure - version 7 /// [Deprecated on 13.09.2018, expires on 13.12.2018] /// struct MaterialInfo7 { MaterialDomain Domain; OldMaterialBlendMode BlendMode; MaterialFlags_Deprecated Flags; MaterialTransparentLighting_Deprecated TransparentLighting; MaterialDecalBlendingMode DecalBlendingMode; MaterialPostFxLocation PostFxLocation; float MaskThreshold; float OpacityThreshold; TessellationMethod TessellationMode; int32 MaxTessellationFactor; MaterialInfo7() { } MaterialInfo7(const MaterialInfo6& other) { Domain = other.Domain; BlendMode = other.BlendMode; Flags = other.Flags; TransparentLighting = other.TransparentLighting; DecalBlendingMode = other.DecalBlendingMode; PostFxLocation = other.PostFxLocation; MaskThreshold = other.MaskThreshold; OpacityThreshold = other.OpacityThreshold; TessellationMode = TessellationMethod::None; MaxTessellationFactor = 15; } /// /// Compare structure with other one /// /// Other structure to compare /// True if both structures are equal bool operator==(const MaterialInfo7& other) const { return Domain == other.Domain && BlendMode == other.BlendMode && TransparentLighting == other.TransparentLighting && DecalBlendingMode == other.DecalBlendingMode && PostFxLocation == other.PostFxLocation && Math::NearEqual(MaskThreshold, other.MaskThreshold) && Math::NearEqual(OpacityThreshold, other.OpacityThreshold) && Flags == other.Flags && TessellationMode == other.TessellationMode && MaxTessellationFactor == other.MaxTessellationFactor; } }; /// /// Material info structure - version 8 /// [Deprecated on 24.07.2019, expires on 10.05.2021] /// struct MaterialInfo8 { MaterialDomain Domain; MaterialBlendMode BlendMode; MaterialShadingModel ShadingModel; MaterialFlags_Deprecated Flags; MaterialTransparentLighting_Deprecated TransparentLighting; MaterialDecalBlendingMode DecalBlendingMode; MaterialPostFxLocation PostFxLocation; float MaskThreshold; float OpacityThreshold; TessellationMethod TessellationMode; int32 MaxTessellationFactor; MaterialInfo8() { } MaterialInfo8(const MaterialInfo7& other) { Domain = other.Domain; switch (other.BlendMode) { case OldMaterialBlendMode::Opaque: BlendMode = MaterialBlendMode::Opaque; ShadingModel = MaterialShadingModel::Lit; break; case OldMaterialBlendMode::Transparent: BlendMode = MaterialBlendMode::Transparent; ShadingModel = MaterialShadingModel::Lit; break; case OldMaterialBlendMode::Unlit: BlendMode = MaterialBlendMode::Opaque; ShadingModel = MaterialShadingModel::Unlit; break; } Flags = other.Flags; TransparentLighting = other.TransparentLighting; DecalBlendingMode = other.DecalBlendingMode; PostFxLocation = other.PostFxLocation; MaskThreshold = other.MaskThreshold; OpacityThreshold = other.OpacityThreshold; TessellationMode = other.TessellationMode; MaxTessellationFactor = other.MaxTessellationFactor; } /// /// Compare structure with other one /// /// Other structure to compare /// True if both structures are equal bool operator==(const MaterialInfo8& other) const { return Domain == other.Domain && BlendMode == other.BlendMode && ShadingModel == other.ShadingModel && TransparentLighting == other.TransparentLighting && DecalBlendingMode == other.DecalBlendingMode && PostFxLocation == other.PostFxLocation && Math::NearEqual(MaskThreshold, other.MaskThreshold) && Math::NearEqual(OpacityThreshold, other.OpacityThreshold) && Flags == other.Flags && TessellationMode == other.TessellationMode && MaxTessellationFactor == other.MaxTessellationFactor; } }; /// /// Structure with basic information about the material surface. It describes how material is reacting on light and which graphical features of it requires to render. /// API_STRUCT() struct FLAXENGINE_API MaterialInfo { DECLARE_SCRIPTING_TYPE_MINIMAL(MaterialInfo); /// /// The material shader domain. /// API_FIELD() MaterialDomain Domain; /// /// The blending mode for rendering. /// API_FIELD() MaterialBlendMode BlendMode; /// /// The shading mode for lighting. /// API_FIELD() MaterialShadingModel ShadingModel; /// /// The usage flags. /// API_FIELD() MaterialUsageFlags UsageFlags; /// /// The features usage flags. /// API_FIELD() MaterialFeaturesFlags FeaturesFlags; /// /// The decal material blending mode. /// API_FIELD() MaterialDecalBlendingMode DecalBlendingMode; /// /// The post fx material rendering location. /// API_FIELD() MaterialPostFxLocation PostFxLocation; /// /// The primitives culling mode. /// API_FIELD() CullMode CullMode; /// /// The mask threshold. /// API_FIELD() float MaskThreshold; /// /// The opacity threshold. /// API_FIELD() float OpacityThreshold; /// /// The tessellation mode. /// API_FIELD() TessellationMethod TessellationMode; /// /// The maximum tessellation factor (used only if material uses tessellation). /// API_FIELD() int32 MaxTessellationFactor; MaterialInfo() { } MaterialInfo(const MaterialInfo8& other) { Domain = other.Domain; BlendMode = other.BlendMode; ShadingModel = other.ShadingModel; UsageFlags = MaterialUsageFlags::None; if (other.Flags & MaterialFlags_Deprecated::UseMask) UsageFlags |= MaterialUsageFlags::UseMask; if (other.Flags & MaterialFlags_Deprecated::UseEmissive) UsageFlags |= MaterialUsageFlags::UseEmissive; if (other.Flags & MaterialFlags_Deprecated::UsePositionOffset) UsageFlags |= MaterialUsageFlags::UsePositionOffset; if (other.Flags & MaterialFlags_Deprecated::UseVertexColor) UsageFlags |= MaterialUsageFlags::UseVertexColor; if (other.Flags & MaterialFlags_Deprecated::UseNormal) UsageFlags |= MaterialUsageFlags::UseNormal; if (other.Flags & MaterialFlags_Deprecated::UseDisplacement) UsageFlags |= MaterialUsageFlags::UseDisplacement; if (other.Flags & MaterialFlags_Deprecated::UseRefraction) UsageFlags |= MaterialUsageFlags::UseRefraction; FeaturesFlags = MaterialFeaturesFlags::None; if (other.Flags & MaterialFlags_Deprecated::Wireframe) FeaturesFlags |= MaterialFeaturesFlags::Wireframe; if (other.Flags & MaterialFlags_Deprecated::TransparentDisableDepthTest && BlendMode != MaterialBlendMode::Opaque) FeaturesFlags |= MaterialFeaturesFlags::DisableDepthTest; if (other.Flags & MaterialFlags_Deprecated::TransparentDisableFog && BlendMode != MaterialBlendMode::Opaque) FeaturesFlags |= MaterialFeaturesFlags::DisableFog; if (other.Flags & MaterialFlags_Deprecated::TransparentDisableReflections && BlendMode != MaterialBlendMode::Opaque) FeaturesFlags |= MaterialFeaturesFlags::DisableReflections; if (other.Flags & MaterialFlags_Deprecated::DisableDepthWrite) FeaturesFlags |= MaterialFeaturesFlags::DisableDepthWrite; if (other.Flags & MaterialFlags_Deprecated::TransparentDisableDistortion && BlendMode != MaterialBlendMode::Opaque) FeaturesFlags |= MaterialFeaturesFlags::DisableDistortion; if (other.Flags & MaterialFlags_Deprecated::InputWorldSpaceNormal) FeaturesFlags |= MaterialFeaturesFlags::InputWorldSpaceNormal; if (other.Flags & MaterialFlags_Deprecated::UseDitheredLODTransition) FeaturesFlags |= MaterialFeaturesFlags::DitheredLODTransition; if (other.BlendMode != MaterialBlendMode::Opaque && other.TransparentLighting == MaterialTransparentLighting_Deprecated::None) ShadingModel = MaterialShadingModel::Unlit; DecalBlendingMode = other.DecalBlendingMode; PostFxLocation = other.PostFxLocation; CullMode = other.Flags & MaterialFlags_Deprecated::TwoSided ? ::CullMode::TwoSided : ::CullMode::Normal; MaskThreshold = other.MaskThreshold; OpacityThreshold = other.OpacityThreshold; TessellationMode = other.TessellationMode; MaxTessellationFactor = other.MaxTessellationFactor; } bool operator==(const MaterialInfo& other) const { return Domain == other.Domain && BlendMode == other.BlendMode && ShadingModel == other.ShadingModel && UsageFlags == other.UsageFlags && FeaturesFlags == other.FeaturesFlags && DecalBlendingMode == other.DecalBlendingMode && PostFxLocation == other.PostFxLocation && CullMode == other.CullMode && Math::NearEqual(MaskThreshold, other.MaskThreshold) && Math::NearEqual(OpacityThreshold, other.OpacityThreshold) && TessellationMode == other.TessellationMode && MaxTessellationFactor == other.MaxTessellationFactor; } }; // The current material info descriptor version used by the material pipeline typedef MaterialInfo MaterialInfo9; #define MaterialInfo_Version 9