diff --git a/Source/Engine/Foliage/Foliage.cpp b/Source/Engine/Foliage/Foliage.cpp index efe89bf5c..459f1b662 100644 --- a/Source/Engine/Foliage/Foliage.cpp +++ b/Source/Engine/Foliage/Foliage.cpp @@ -22,7 +22,7 @@ #include "Engine/Serialization/Serialization.h" #include "Engine/Utilities/Encryption.h" -#define FOLIAGE_GET_DRAW_MODES(renderContext, type) (type.DrawModes & renderContext.View.Pass & renderContext.View.GetShadowsDrawPassMask(type.ShadowsMode)) +#define FOLIAGE_GET_DRAW_MODES(renderContext, type) (type._drawModes & renderContext.View.Pass & renderContext.View.GetShadowsDrawPassMask(type.ShadowsMode)) #define FOLIAGE_CAN_DRAW(renderContext, type) (type.IsReady() && FOLIAGE_GET_DRAW_MODES(renderContext, type) != DrawPass::None && type.Model->CanBeRendered()) Foliage::Foliage(const SpawnParams& params) @@ -360,7 +360,7 @@ void Foliage::DrawCluster(DrawContext& context, FoliageCluster* cluster, Mesh::D draw.DrawState = &instance.DrawState; draw.Bounds = sphere; draw.PerInstanceRandom = instance.Random; - draw.DrawModes = type.DrawModes; + draw.DrawModes = type._drawModes; draw.SetStencilValue(_layer); type.Model->Draw(context.RenderContext, draw); @@ -597,14 +597,22 @@ void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, Me void Foliage::InitType(const RenderView& view, FoliageType& type) { - const DrawPass drawModes = type.DrawModes & view.Pass & view.GetShadowsDrawPassMask(type.ShadowsMode); + const DrawPass drawModes = type._drawModes & view.Pass & view.GetShadowsDrawPassMask(type.ShadowsMode); type._canDraw = type.IsReady() && drawModes != DrawPass::None && type.Model && type.Model->CanBeRendered(); + bool drawModesDirty = false; for (int32 j = 0; j < type.Entries.Count(); j++) { auto& e = type.Entries[j]; e.ReceiveDecals = type.ReceiveDecals != 0; e.ShadowsMode = type.ShadowsMode; + if (type._drawModesDirty) + { + type._drawModesDirty = 0; + drawModesDirty = true; + } } + if (drawModesDirty) + GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, ISceneRenderingListener::DrawModes); } int32 Foliage::GetInstancesCount() const @@ -1250,7 +1258,7 @@ void Foliage::Draw(RenderContext& renderContext) draw.Deformation = nullptr; draw.Bounds = instance.Bounds; draw.PerInstanceRandom = instance.Random; - draw.DrawModes = type.DrawModes & view.Pass & view.GetShadowsDrawPassMask(type.ShadowsMode); + draw.DrawModes = type._drawModes & view.Pass & view.GetShadowsDrawPassMask(type.ShadowsMode); draw.SetStencilValue(_layer); type.Model->Draw(renderContext, draw); return; diff --git a/Source/Engine/Foliage/FoliageType.cpp b/Source/Engine/Foliage/FoliageType.cpp index 8b8c84420..e9eb63b2d 100644 --- a/Source/Engine/Foliage/FoliageType.cpp +++ b/Source/Engine/Foliage/FoliageType.cpp @@ -13,6 +13,7 @@ FoliageType::FoliageType() , Index(-1) { _isReady = 0; + _drawModesDirty = 0; ReceiveDecals = true; UseDensityScaling = false; @@ -32,7 +33,7 @@ FoliageType& FoliageType::operator=(const FoliageType& other) CullDistance = other.CullDistance; CullDistanceRandomRange = other.CullDistanceRandomRange; ScaleInLightmap = other.ScaleInLightmap; - DrawModes = other.DrawModes; + SetDrawModes(other._drawModes); ShadowsMode = other.ShadowsMode; PaintDensity = other.PaintDensity; PaintRadius = other.PaintRadius; @@ -69,6 +70,19 @@ void FoliageType::SetMaterials(const Array& value) Entries[i].Material = value[i]; } +DrawPass FoliageType::GetDrawModes() const +{ + return _drawModes; +} + +void FoliageType::SetDrawModes(DrawPass value) +{ + if (_drawModes == value) + return; + _drawModes = value; + _drawModesDirty = 1; +} + Float3 FoliageType::GetRandomScale() const { Float3 result; @@ -150,7 +164,7 @@ void FoliageType::Serialize(SerializeStream& stream, const void* otherObj) SERIALIZE(CullDistance); SERIALIZE(CullDistanceRandomRange); SERIALIZE(ScaleInLightmap); - SERIALIZE(DrawModes); + SERIALIZE_MEMBER(DrawModes, _drawModes); SERIALIZE(ShadowsMode); SERIALIZE_BIT(ReceiveDecals); SERIALIZE_BIT(UseDensityScaling); @@ -191,7 +205,7 @@ void FoliageType::Deserialize(DeserializeStream& stream, ISerializeModifier* mod DESERIALIZE(CullDistance); DESERIALIZE(CullDistanceRandomRange); DESERIALIZE(ScaleInLightmap); - DESERIALIZE(DrawModes); + DESERIALIZE_MEMBER(DrawModes, _drawModes); DESERIALIZE(ShadowsMode); DESERIALIZE_BIT(ReceiveDecals); DESERIALIZE_BIT(UseDensityScaling); diff --git a/Source/Engine/Foliage/FoliageType.h b/Source/Engine/Foliage/FoliageType.h index 224ed0bd8..8b36f618b 100644 --- a/Source/Engine/Foliage/FoliageType.h +++ b/Source/Engine/Foliage/FoliageType.h @@ -48,6 +48,8 @@ API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API FoliageType : public ScriptingOb private: uint8 _isReady : 1; uint8 _canDraw : 1; + uint8 _drawModesDirty : 1; + DrawPass _drawModes = DrawPass::Depth | DrawPass::GBuffer | DrawPass::Forward; public: /// @@ -124,9 +126,15 @@ public: API_FIELD() float ScaleInLightmap = 1.0f; /// - /// The draw passes to use for rendering this foliage type. + /// Gets the draw passes to use for rendering this foliage type. /// - API_FIELD() DrawPass DrawModes = DrawPass::Depth | DrawPass::GBuffer | DrawPass::Forward; + API_PROPERTY(Attributes="DefaultValue(DrawPass.Depth | DrawPass.GBuffer | DrawPass.Forward)") + DrawPass GetDrawModes() const; + + /// + /// Sets the draw passes to use for rendering this foliage type. + /// + API_PROPERTY() void SetDrawModes(DrawPass value); /// /// The shadows casting mode. @@ -184,7 +192,7 @@ public: API_FIELD() float PlacementRandomRollAngle = 0.0f; /// - /// The density scaling scale applied to the global scale for the foliage instances of this type. Can be used to boost or reduce density scaling effect on this foliage type. Default is 1. + /// The density scale factor applied to the global scale for the foliage instances of this type. Can be used to boost or reduce density scaling effect on this foliage type. Default is 1. Lower to reduce density scaling effect when downscaling foliage via global quality/scalability. /// API_FIELD() float DensityScalingScale = 1.0f; diff --git a/Source/Engine/Level/Actors/StaticModel.cpp b/Source/Engine/Level/Actors/StaticModel.cpp index f41e4a805..19e4e3f34 100644 --- a/Source/Engine/Level/Actors/StaticModel.cpp +++ b/Source/Engine/Level/Actors/StaticModel.cpp @@ -66,6 +66,20 @@ void StaticModel::SetBoundsScale(float value) UpdateBounds(); } +DrawPass StaticModel::GetDrawModes() const +{ + return _drawModes; +} + +void StaticModel::SetDrawModes(DrawPass value) +{ + if (_drawModes == value) + return; + _drawModes = value; + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, ISceneRenderingListener::DrawModes); +} + int32 StaticModel::GetLODBias() const { return _lodBias; @@ -330,13 +344,13 @@ void StaticModel::Draw(RenderContext& renderContext) return; if (renderContext.View.Pass == DrawPass::GlobalSDF) { - if (EnumHasAnyFlags(DrawModes, DrawPass::GlobalSDF) && Model->SDF.Texture) + if (EnumHasAnyFlags(_drawModes, DrawPass::GlobalSDF) && Model->SDF.Texture) GlobalSignDistanceFieldPass::Instance()->RasterizeModelSDF(this, Model->SDF, _transform, _box); return; } if (renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas) { - if (EnumHasAnyFlags(DrawModes, DrawPass::GlobalSurfaceAtlas) && Model->SDF.Texture) + if (EnumHasAnyFlags(_drawModes, DrawPass::GlobalSurfaceAtlas) && Model->SDF.Texture) GlobalSurfaceAtlasPass::Instance()->RasterizeActor(this, this, _sphere, _transform, Model->LODs.Last().GetBox()); return; } @@ -353,7 +367,7 @@ void StaticModel::Draw(RenderContext& renderContext) draw.Lightmap = _scene ? _scene->LightmapsData.GetReadyLightmap(Lightmap.TextureIndex) : nullptr; draw.LightmapUVs = &Lightmap.UVsArea; draw.Flags = _staticFlags; - draw.DrawModes = DrawModes; + draw.DrawModes = _drawModes; draw.Bounds = _sphere; draw.Bounds.Center -= renderContext.View.Origin; draw.PerInstanceRandom = GetPerInstanceRandom(); @@ -390,7 +404,7 @@ void StaticModel::Draw(RenderContextBatch& renderContextBatch) draw.Lightmap = _scene ? _scene->LightmapsData.GetReadyLightmap(Lightmap.TextureIndex) : nullptr; draw.LightmapUVs = &Lightmap.UVsArea; draw.Flags = _staticFlags; - draw.DrawModes = DrawModes; + draw.DrawModes = _drawModes; draw.Bounds = _sphere; draw.Bounds.Center -= renderContext.View.Origin; draw.PerInstanceRandom = GetPerInstanceRandom(); @@ -435,7 +449,7 @@ void StaticModel::Serialize(SerializeStream& stream, const void* otherObj) SERIALIZE_MEMBER(LODBias, _lodBias); SERIALIZE_MEMBER(ForcedLOD, _forcedLod); SERIALIZE_MEMBER(SortOrder, _sortOrder); - SERIALIZE(DrawModes); + SERIALIZE_MEMBER(DrawModes, _drawModes); if (HasLightmap() #if USE_EDITOR @@ -487,7 +501,7 @@ void StaticModel::Deserialize(DeserializeStream& stream, ISerializeModifier* mod DESERIALIZE_MEMBER(LODBias, _lodBias); DESERIALIZE_MEMBER(ForcedLOD, _forcedLod); DESERIALIZE_MEMBER(SortOrder, _sortOrder); - DESERIALIZE(DrawModes); + DESERIALIZE_MEMBER(DrawModes, _drawModes); DESERIALIZE_MEMBER(LightmapIndex, Lightmap.TextureIndex); DESERIALIZE_MEMBER(LightmapArea, Lightmap.UVsArea); @@ -537,27 +551,27 @@ void StaticModel::Deserialize(DeserializeStream& stream, ISerializeModifier* mod if (member != stream.MemberEnd() && member->value.IsBool() && member->value.GetBool()) { MARK_CONTENT_DEPRECATED(); - DrawModes = DrawPass::Depth; + _drawModes = DrawPass::Depth; } } // [Deprecated on 07.02.2022, expires on 07.02.2024] if (modifier->EngineBuild <= 6330) { MARK_CONTENT_DEPRECATED(); - DrawModes |= DrawPass::GlobalSDF; + _drawModes |= DrawPass::GlobalSDF; } // [Deprecated on 27.04.2022, expires on 27.04.2024] if (modifier->EngineBuild <= 6331) { MARK_CONTENT_DEPRECATED(); - DrawModes |= DrawPass::GlobalSurfaceAtlas; + _drawModes |= DrawPass::GlobalSurfaceAtlas; } { const auto member = stream.FindMember("RenderPasses"); if (member != stream.MemberEnd() && member->value.IsInt()) { - DrawModes = (DrawPass)member->value.GetInt(); + _drawModes = (DrawPass)member->value.GetInt(); } } } diff --git a/Source/Engine/Level/Actors/StaticModel.h b/Source/Engine/Level/Actors/StaticModel.h index e6ed701cc..4b575a0ed 100644 --- a/Source/Engine/Level/Actors/StaticModel.h +++ b/Source/Engine/Level/Actors/StaticModel.h @@ -23,6 +23,7 @@ private: bool _vertexColorsDirty; byte _vertexColorsCount; int8 _sortOrder; + DrawPass _drawModes = DrawPass::Default; Array _vertexColorsData[MODEL_MAX_LODS]; GPUBuffer* _vertexColorsBuffer[MODEL_MAX_LODS]; Model* _residencyChangedModel = nullptr; @@ -40,12 +41,6 @@ public: API_FIELD(Attributes="EditorOrder(20), DefaultValue(null), EditorDisplay(\"Model\")") AssetReference Model; - /// - /// The draw passes to use for rendering this object. - /// - API_FIELD(Attributes="EditorOrder(15), DefaultValue(DrawPass.Default), EditorDisplay(\"Model\")") - DrawPass DrawModes = DrawPass::Default; - /// /// The baked lightmap entry. /// @@ -74,6 +69,17 @@ public: /// API_PROPERTY() void SetBoundsScale(float value); + /// + /// Gets the draw passes to use for rendering this object. + /// + API_PROPERTY(Attributes="EditorOrder(15), DefaultValue(DrawPass.Default), EditorDisplay(\"Model\")") + DrawPass GetDrawModes() const; + + /// + /// Sets the draw passes to use for rendering this object. + /// + API_PROPERTY() void SetDrawModes(DrawPass value); + /// /// Gets the model Level Of Detail bias value. Allows to increase or decrease rendered model quality. /// diff --git a/Source/Engine/Level/Scene/SceneRendering.h b/Source/Engine/Level/Scene/SceneRendering.h index 25dfc63fa..d522454a6 100644 --- a/Source/Engine/Level/Scene/SceneRendering.h +++ b/Source/Engine/Level/Scene/SceneRendering.h @@ -56,6 +56,7 @@ public: Layer = 4, StaticFlags = 8, AutoDelayDuringRendering = 16, // Conditionally allow updating data during rendering when writes are locked + DrawModes = 32, Auto = Visual | Bounds | Layer, }; diff --git a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp index 010e14bf9..ae6e8a9a8 100644 --- a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp +++ b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp @@ -408,7 +408,8 @@ public: if (GLOBAL_SDF_ACTOR_IS_STATIC(a) && ObjectTypes.Contains(a->GetTypeHandle())) { ScopeWriteLock lock(Locker); - OnSceneRenderingDirty(BoundingBox::FromSphere(prevBounds)); + if (flags != DrawModes && flags != Layer && flags != StaticFlags) + OnSceneRenderingDirty(BoundingBox::FromSphere(prevBounds)); OnSceneRenderingDirty(a->GetBox()); } }