Refactor GeometryDrawStateData storage into RenderBufers for correct split-screen rendering
Refactor `ISceneRenderingListener` events to contain more data
This commit is contained in:
@@ -130,8 +130,6 @@ void ViewportIconsRendererService::DrawIcons(RenderContext& renderContext, Scene
|
||||
const BoundingFrustum frustum = view.Frustum;
|
||||
const auto& icons = scene->GetSceneRendering()->ViewportIcons;
|
||||
Matrix m1, m2, world;
|
||||
GeometryDrawStateData drawState;
|
||||
draw.DrawState = &drawState;
|
||||
draw.World = &world;
|
||||
AssetReference<Texture> texture;
|
||||
for (Actor* icon : icons)
|
||||
@@ -211,10 +209,6 @@ void ViewportIconsRendererService::DrawIcons(RenderContext& renderContext, Actor
|
||||
Matrix::Billboard(sphere.Center, view.Position, Vector3::Up, view.Direction, m2);
|
||||
Matrix::Multiply(m1, m2, world);
|
||||
|
||||
// Draw icon
|
||||
GeometryDrawStateData drawState;
|
||||
draw.DrawState = &drawState;
|
||||
|
||||
// Support custom icons through types, but not ones that were added through actors, since they cant register while in prefab view anyway
|
||||
if (ActorTypeToTexture.TryGet(actor->GetTypeHandle(), texture))
|
||||
{
|
||||
@@ -227,9 +221,7 @@ void ViewportIconsRendererService::DrawIcons(RenderContext& renderContext, Actor
|
||||
draw.Buffer->At(0).ReceiveDecals = false;
|
||||
draw.Buffer->At(0).ShadowsMode = ShadowsCastingMode::None;
|
||||
}
|
||||
|
||||
AssetReference<MaterialBase> material;
|
||||
|
||||
if (!TextureToMaterial.TryGet(texture, material))
|
||||
{
|
||||
// Create custom material per custom texture
|
||||
@@ -237,7 +229,6 @@ void ViewportIconsRendererService::DrawIcons(RenderContext& renderContext, Actor
|
||||
TextureToMaterial[texture]->SetParameterValue(TEXT("Image"), Variant(texture));
|
||||
material = TextureToMaterial[texture];
|
||||
}
|
||||
|
||||
draw.Buffer->At(0).Material = material;
|
||||
}
|
||||
else
|
||||
@@ -246,6 +237,7 @@ void ViewportIconsRendererService::DrawIcons(RenderContext& renderContext, Actor
|
||||
draw.Buffer = &InstanceBuffers[static_cast<int32>(iconType)];
|
||||
}
|
||||
|
||||
// Draw icon
|
||||
draw.World = &world;
|
||||
draw.Bounds = sphere;
|
||||
QuadModel->Draw(renderContext, draw);
|
||||
|
||||
@@ -228,7 +228,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="index">The index.</param>
|
||||
/// <returns><c>true</c> if is valid a index; otherwise, <c>false</c>.</returns>
|
||||
bool IsValidIndex(const int32 index) const
|
||||
FORCE_INLINE bool IsValidIndex(const int32 index) const
|
||||
{
|
||||
return index < _count && index >= 0;
|
||||
}
|
||||
|
||||
@@ -356,8 +356,6 @@ void Foliage::DrawCluster(DrawContext& context, FoliageCluster* cluster, Mesh::D
|
||||
Matrix::Transformation(transform.Scale, transform.Orientation, translation, world);
|
||||
|
||||
// Disable motion blur
|
||||
GeometryDrawStateData drawState;
|
||||
drawState.PrevWorld = world;
|
||||
instance.DrawState.PrevWorld = world;
|
||||
|
||||
// Draw model
|
||||
@@ -365,7 +363,6 @@ void Foliage::DrawCluster(DrawContext& context, FoliageCluster* cluster, Mesh::D
|
||||
draw.LightmapUVs = &instance.Lightmap.UVsArea;
|
||||
draw.Buffer = &type.Entries;
|
||||
draw.World = &world;
|
||||
draw.DrawState = &drawState;
|
||||
draw.Bounds = sphere;
|
||||
draw.PerInstanceRandom = instance.Random;
|
||||
draw.DrawModes = type._drawModes;
|
||||
@@ -1290,15 +1287,12 @@ void Foliage::Draw(RenderContext& renderContext)
|
||||
Matrix world;
|
||||
const Transform transform = _transform.LocalToWorld(instance.Transform);
|
||||
renderContext.View.GetWorldMatrix(transform, world);
|
||||
GeometryDrawStateData drawState;
|
||||
drawState.PrevWorld = world;
|
||||
Mesh::DrawInfo draw;
|
||||
draw.Flags = GetStaticFlags();
|
||||
draw.Lightmap = _scene ? _scene->LightmapsData.GetReadyLightmap(instance.LightmapTextureIndex) : nullptr;
|
||||
draw.LightmapUVs = &instance.LightmapUVsArea;
|
||||
draw.Buffer = &type.Entries;
|
||||
draw.World = &world;
|
||||
draw.DrawState = &drawState;
|
||||
draw.Bounds = instance.Bounds;
|
||||
draw.PerInstanceRandom = instance.Random;
|
||||
draw.DrawModes = type._drawModes & view.Pass & view.GetShadowsDrawPassMask(type.ShadowsMode);
|
||||
|
||||
@@ -302,7 +302,7 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = (float)info.Bounds.Radius; // TODO: should it be kept in sync with ObjectPosition?
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
|
||||
drawCall.Surface.PrevWorld = info.DrawState ? info.DrawState->PrevWorld : drawCall.World;
|
||||
drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr;
|
||||
drawCall.Surface.LightmapUVsArea = info.LightmapUVs ? *info.LightmapUVs : Half4::Zero;
|
||||
drawCall.Surface.LODDitherFactor = (int8)(lodDitherFactor * 127);
|
||||
@@ -365,7 +365,7 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = (float)info.Bounds.Radius; // TODO: should it be kept in sync with ObjectPosition?
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
|
||||
drawCall.Surface.PrevWorld = info.DrawState ? info.DrawState->PrevWorld : drawCall.World;
|
||||
drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr;
|
||||
drawCall.Surface.LightmapUVsArea = info.LightmapUVs ? *info.LightmapUVs : Half4::Zero;
|
||||
drawCall.Surface.LODDitherFactor = (int8)(lodDitherFactor * 127);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "CollisionProxy.h"
|
||||
#endif
|
||||
|
||||
struct GeometryDrawStateData;
|
||||
struct GeometryDrawState;
|
||||
struct RenderContext;
|
||||
struct RenderContextBatch;
|
||||
class Task;
|
||||
@@ -347,9 +347,9 @@ public:
|
||||
Matrix* World;
|
||||
|
||||
/// <summary>
|
||||
/// The instance drawing state data container. Used for LOD transition handling and previous world transformation matrix updating.
|
||||
/// The instance drawing state data container (optional). Used for LOD transition handling and previous world transformation matrix updating.
|
||||
/// </summary>
|
||||
GeometryDrawStateData* DrawState;
|
||||
GeometryDrawState* DrawState;
|
||||
|
||||
/// <summary>
|
||||
/// The instance deformation utility.
|
||||
|
||||
@@ -31,6 +31,18 @@ FORCE_INLINE void ModelDraw(ModelType* model, const RenderContext& renderContext
|
||||
return;
|
||||
if (!info.Buffer->IsValidFor(model))
|
||||
info.Buffer->Setup(model);
|
||||
if (!info.DrawState || renderContext.View.IsSingleFrame)
|
||||
{
|
||||
// No LOD transition
|
||||
int32 lodIndex = info.ForcedLOD != -1 ? info.ForcedLOD : RenderTools::ComputeModelLOD(model, info.Bounds.Center, (float)info.Bounds.Radius, renderContext);
|
||||
if (lodIndex != -1)
|
||||
{
|
||||
lodIndex += info.LODBias + renderContext.View.ModelLODBias;
|
||||
lodIndex = model->ClampLODIndex(lodIndex);
|
||||
model->LODs.Get()[lodIndex].Draw(context, info, 0.0f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const auto frame = Engine::FrameCount;
|
||||
const auto modelFrame = info.DrawState->PrevFrame + 1;
|
||||
|
||||
@@ -46,7 +58,7 @@ FORCE_INLINE void ModelDraw(ModelType* model, const RenderContext& renderContext
|
||||
if (lodIndex == -1)
|
||||
{
|
||||
// Handling model fade-out transition
|
||||
if (modelFrame == frame && info.DrawState->PrevLOD != -1 && !renderContext.View.IsSingleFrame && ModelDrawTransition(model, info))
|
||||
if (modelFrame == frame && info.DrawState->PrevLOD != -1 && ModelDrawTransition(model, info))
|
||||
{
|
||||
// Check if start transition
|
||||
if (info.DrawState->LODTransition == 255)
|
||||
@@ -75,11 +87,8 @@ FORCE_INLINE void ModelDraw(ModelType* model, const RenderContext& renderContext
|
||||
lodIndex += info.LODBias + renderContext.View.ModelLODBias;
|
||||
lodIndex = model->ClampLODIndex(lodIndex);
|
||||
|
||||
if (renderContext.View.IsSingleFrame)
|
||||
{
|
||||
}
|
||||
// Check if it's the new frame and could update the drawing state (note: model instance could be rendered many times per frame to different viewports)
|
||||
else if (modelFrame == frame)
|
||||
if (modelFrame == frame)
|
||||
{
|
||||
// Check if materials use transition
|
||||
if (!ModelDrawTransition(model, info))
|
||||
@@ -111,7 +120,7 @@ FORCE_INLINE void ModelDraw(ModelType* model, const RenderContext& renderContext
|
||||
}
|
||||
|
||||
// Draw
|
||||
if (info.DrawState->PrevLOD == lodIndex || info.DrawState->LODTransition == 255 || renderContext.View.IsSingleFrame)
|
||||
if (info.DrawState->PrevLOD == lodIndex || info.DrawState->LODTransition == 255)
|
||||
{
|
||||
model->LODs.Get()[lodIndex].Draw(context, info, 0.0f);
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ void SkinnedMesh::Draw(const RenderContext& renderContext, const DrawInfo& info,
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = (float)info.Bounds.Radius; // TODO: should it be kept in sync with ObjectPosition?
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
|
||||
drawCall.Surface.PrevWorld = info.DrawState ? info.DrawState->PrevWorld : drawCall.World;
|
||||
drawCall.Surface.Skinning = info.WithPrevBones ? DrawCall::SkinningMode::WithPrevBones : DrawCall::SkinningMode::Active;
|
||||
drawCall.Surface.SkinningBones = info.SkinningBones;
|
||||
drawCall.Surface.SkinningBonesOffset = info.SkinningBonesOffset;
|
||||
@@ -422,7 +422,7 @@ void SkinnedMesh::Draw(const RenderContextBatch& renderContextBatch, const DrawI
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = (float)info.Bounds.Radius; // TODO: should it be kept in sync with ObjectPosition?
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
|
||||
drawCall.Surface.PrevWorld = info.DrawState ? info.DrawState->PrevWorld : drawCall.World;
|
||||
drawCall.Surface.Skinning = info.WithPrevBones ? DrawCall::SkinningMode::WithPrevBones : DrawCall::SkinningMode::Active;
|
||||
drawCall.Surface.SkinningBones = info.SkinningBones;
|
||||
drawCall.Surface.SkinningBonesOffset = info.SkinningBonesOffset;
|
||||
|
||||
@@ -304,3 +304,66 @@ RenderBuffers::ReadOnlyDepthBuffer RenderBuffers::GetReadOnlyDepthBuffer() const
|
||||
GPUTextureView* depthBufferSRV = depthBufferReadOnly ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
|
||||
return { depthBufferRTV, depthBufferSRV };
|
||||
}
|
||||
|
||||
void RenderBuffers::OnSceneRendering(SceneRendering* scene)
|
||||
{
|
||||
if (!Scenes.ContainsKey(scene))
|
||||
{
|
||||
PROFILE_CPU_NAMED("Init Scene");
|
||||
|
||||
// Register scene
|
||||
auto& sceneData = Scenes[scene];
|
||||
ListenSceneRendering(scene);
|
||||
|
||||
// Put all existing actors into the render buffer geo storage used for LOD transitions, etc.
|
||||
for (int32 i = 0; i < SceneRendering::MAX; i++)
|
||||
{
|
||||
auto& list = scene->Actors[i];
|
||||
auto& geo = sceneData.Geo[i];
|
||||
geo.Resize(list.Count());
|
||||
auto geoPtr = geo.Get();
|
||||
for (int32 j = 0; j < list.Count(); j++)
|
||||
geoPtr[j] = GeometryDrawState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GeometryDrawState* RenderBuffers::GetGeometryDrawState(SceneRendering* scene, int32 key, const Actor* actor) const
|
||||
{
|
||||
if (auto* sceneData = Scenes.TryGet(scene))
|
||||
{
|
||||
auto& list = sceneData->Geo[actor->_drawCategory];
|
||||
if (list.IsValidIndex(key))
|
||||
{
|
||||
return list.Get() + key;
|
||||
}
|
||||
}
|
||||
// TODO: what about loose actors drawn from code? dynamically manage their state here?
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RenderBuffers::OnSceneRenderingAddActor(SceneRendering* scene, int32 key, Actor* a)
|
||||
{
|
||||
// Init geo state of that object
|
||||
if (auto* sceneData = Scenes.TryGet(scene))
|
||||
{
|
||||
auto& list = sceneData->Geo[a->_drawCategory];
|
||||
ASSERT(key >= 0);
|
||||
if (list.Count() <= key)
|
||||
list.Resize(key + 1);
|
||||
list.Get()[key] = GeometryDrawState();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderBuffers::OnSceneRenderingUpdateActor(SceneRendering* scene, int32 key, Actor* a, const BoundingSphere& prevBounds, UpdateFlags flags)
|
||||
{
|
||||
}
|
||||
|
||||
void RenderBuffers::OnSceneRenderingRemoveActor(SceneRendering* scene, int32 key, Actor* a)
|
||||
{
|
||||
}
|
||||
|
||||
void RenderBuffers::OnSceneRenderingClear(SceneRendering* scene)
|
||||
{
|
||||
Scenes.Remove(scene);
|
||||
}
|
||||
|
||||
@@ -4,8 +4,11 @@
|
||||
|
||||
#include "Engine/Core/Math/Viewport.h"
|
||||
#include "Engine/Core/Collections/Array.h"
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
#include "Engine/Scripting/ScriptingObject.h"
|
||||
#include "Engine/Graphics/Textures/GPUTexture.h"
|
||||
#include "Engine/Level/Scene/SceneRendering.h"
|
||||
#include "Engine/Renderer/DrawCall.h"
|
||||
|
||||
// GBuffer render targets formats
|
||||
#define GBUFFER0_FORMAT PixelFormat::R8G8B8A8_UNorm
|
||||
@@ -24,10 +27,13 @@
|
||||
// [7] | <unsued>
|
||||
#define STENCIL_BUFFER_OBJECT_LAYER(value) uint8(value & 0x1f)
|
||||
|
||||
class Actor;
|
||||
class SceneRendering;
|
||||
|
||||
/// <summary>
|
||||
/// The scene rendering buffers container.
|
||||
/// </summary>
|
||||
API_CLASS() class FLAXENGINE_API RenderBuffers : public ScriptingObject
|
||||
API_CLASS() class FLAXENGINE_API RenderBuffers : public ScriptingObject, private ISceneRenderingListener
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE(RenderBuffers);
|
||||
|
||||
@@ -114,6 +120,14 @@ public:
|
||||
// Maps the custom buffer type into the object that holds the state.
|
||||
Array<CustomBuffer*, HeapAllocation> CustomBuffers;
|
||||
|
||||
// Scene drawing cache with the per-object state (eg. LOD transitions, motion-vectors movement)
|
||||
struct SceneData
|
||||
{
|
||||
// Per-object drawing state (eg. LOD transition). Indexing matches actor/object key of object registered in SceneRendering.
|
||||
Array<GeometryDrawState> Geo[SceneRendering::DrawCategory::MAX];
|
||||
};
|
||||
Dictionary<SceneRendering*, SceneData> Scenes;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="RenderBuffers"/> class.
|
||||
@@ -268,4 +282,19 @@ public:
|
||||
/// Gets the depth buffer binding for rendering as read-only (both shader resource and render target).
|
||||
/// </summary>
|
||||
ReadOnlyDepthBuffer GetReadOnlyDepthBuffer() const;
|
||||
|
||||
// Internal event called by SceneRendering to initiate drawing.
|
||||
void OnSceneRendering(SceneRendering* scene);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the geometry drawing state container for a specific actor/object. Returns null for invalid object (-1) or when view is not using LOD transitions (single-shot frame).
|
||||
/// </summary>
|
||||
GeometryDrawState* GetGeometryDrawState(SceneRendering* scene, int32 key, const Actor* actor) const;
|
||||
|
||||
public:
|
||||
// [ISceneRenderingListener]
|
||||
void OnSceneRenderingAddActor(SceneRendering* scene, int32 key, Actor* a) override;
|
||||
void OnSceneRenderingUpdateActor(SceneRendering* scene, int32 key, Actor* a, const BoundingSphere& prevBounds, UpdateFlags flags) override;
|
||||
void OnSceneRenderingRemoveActor(SceneRendering* scene, int32 key, Actor* a) override;
|
||||
void OnSceneRenderingClear(SceneRendering* scene) override;
|
||||
};
|
||||
|
||||
@@ -468,12 +468,12 @@ API_STRUCT(NoDefault) struct FLAXENGINE_API RenderContext
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(RenderContext);
|
||||
|
||||
/// <summary>
|
||||
/// The render buffers.
|
||||
/// The render buffers that contain drawing state (eg. LOD transitions) and scene buffers (eg. GBuffer, DDGI, Shadow Maps).
|
||||
/// </summary>
|
||||
API_FIELD() RenderBuffers* Buffers = nullptr;
|
||||
|
||||
/// <summary>
|
||||
/// The render list.
|
||||
/// The render list that collects draw calls.
|
||||
/// </summary>
|
||||
API_FIELD() RenderList* List = nullptr;
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ API_CLASS(Abstract) class FLAXENGINE_API Actor : public SceneObject
|
||||
friend SceneRendering;
|
||||
friend Prefab;
|
||||
friend PrefabInstanceData;
|
||||
friend class RenderBuffers;
|
||||
protected:
|
||||
uint16 _isActive : 1;
|
||||
uint16 _isActiveInHierarchy : 1;
|
||||
@@ -48,7 +49,7 @@ protected:
|
||||
BoundingBox _box;
|
||||
String _name;
|
||||
Scene* _scene;
|
||||
PhysicsScene* _physicsScene;
|
||||
PhysicsScene* _physicsScene; // TODO: move it into physics-related actors (coliders, rigidbodies, etc.)
|
||||
|
||||
private:
|
||||
// Disable copying
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
#include "Engine/Graphics/GPUPass.h"
|
||||
#include "Engine/Graphics/RenderTask.h"
|
||||
#include "Engine/Graphics/RenderBuffers.h"
|
||||
#include "Engine/Graphics/Models/MeshAccessor.h"
|
||||
#include "Engine/Graphics/Models/MeshDeformation.h"
|
||||
#include "Engine/Renderer/DrawCall.h"
|
||||
#include "Engine/Renderer/RenderList.h"
|
||||
#include "Engine/Level/Scene/Scene.h"
|
||||
#include "Engine/Level/SceneObjectsFactory.h"
|
||||
@@ -1256,8 +1258,9 @@ void AnimatedModel::Draw(RenderContext& renderContext)
|
||||
return;
|
||||
if (renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas)
|
||||
return; // Not supported
|
||||
auto drawState = renderContext.Buffers->GetGeometryDrawState(&GetScene()->Rendering, _sceneRenderingKey, this);
|
||||
ACTOR_GET_WORLD_MATRIX(this, view, world);
|
||||
GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world);
|
||||
GEOMETRY_DRAW_STATE_EVENT_BEGIN(drawState, world);
|
||||
|
||||
_lastMinDstSqr = Math::Min(_lastMinDstSqr, Vector3::DistanceSquared(_transform.Translation, renderContext.View.WorldPosition));
|
||||
if (_bones.IsAllocated)
|
||||
@@ -1281,7 +1284,7 @@ void AnimatedModel::Draw(RenderContext& renderContext)
|
||||
}
|
||||
}
|
||||
draw.World = &world;
|
||||
draw.DrawState = &_drawState;
|
||||
draw.DrawState = drawState;
|
||||
draw.Deformation = _deformation;
|
||||
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
||||
draw.DrawModes = DrawModes & renderContext.View.GetShadowsDrawPassMask(ShadowsMode);
|
||||
@@ -1297,7 +1300,7 @@ void AnimatedModel::Draw(RenderContext& renderContext)
|
||||
SkinnedModel->Draw(renderContext, draw);
|
||||
}
|
||||
|
||||
GEOMETRY_DRAW_STATE_EVENT_END(_drawState, world);
|
||||
GEOMETRY_DRAW_STATE_EVENT_END(drawState, world);
|
||||
}
|
||||
|
||||
void AnimatedModel::Draw(RenderContextBatch& renderContextBatch)
|
||||
@@ -1308,7 +1311,8 @@ void AnimatedModel::Draw(RenderContextBatch& renderContextBatch)
|
||||
Matrix world;
|
||||
const Float3 translation = _transform.Translation - renderContext.View.Origin;
|
||||
Matrix::Transformation(_transform.Scale, _transform.Orientation, translation, world);
|
||||
GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world);
|
||||
auto drawState = renderContext.Buffers->GetGeometryDrawState(&GetScene()->Rendering, _sceneRenderingKey, this);
|
||||
GEOMETRY_DRAW_STATE_EVENT_BEGIN(drawState, world);
|
||||
|
||||
_lastMinDstSqr = Math::Min(_lastMinDstSqr, Vector3::DistanceSquared(_transform.Translation, renderContext.View.WorldPosition));
|
||||
if (_bones.IsAllocated)
|
||||
@@ -1332,7 +1336,7 @@ void AnimatedModel::Draw(RenderContextBatch& renderContextBatch)
|
||||
}
|
||||
}
|
||||
draw.World = &world;
|
||||
draw.DrawState = &_drawState;
|
||||
draw.DrawState = drawState;
|
||||
draw.Deformation = _deformation;
|
||||
draw.DrawModes = DrawModes;
|
||||
draw.Bounds = _sphere;
|
||||
@@ -1361,7 +1365,7 @@ void AnimatedModel::Draw(RenderContextBatch& renderContextBatch)
|
||||
PRAGMA_ENABLE_DEPRECATION_WARNINGS
|
||||
}
|
||||
|
||||
GEOMETRY_DRAW_STATE_EVENT_END(_drawState, world);
|
||||
GEOMETRY_DRAW_STATE_EVENT_END(drawState, world);
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "ModelInstanceActor.h"
|
||||
#include "Engine/Content/Assets/SkinnedModel.h"
|
||||
#include "Engine/Content/Assets/AnimationGraph.h"
|
||||
#include "Engine/Renderer/DrawCall.h"
|
||||
#include "Engine/Core/Delegate.h"
|
||||
|
||||
/// <summary>
|
||||
@@ -96,7 +95,6 @@ private:
|
||||
void Flush();
|
||||
};
|
||||
|
||||
GeometryDrawStateData _drawState;
|
||||
AnimationUpdateMode _actualMode;
|
||||
SkinnedBones _bones;
|
||||
uint32 _counter;
|
||||
|
||||
@@ -366,11 +366,9 @@ void Camera::Draw(RenderContext& renderContext)
|
||||
renderContext.View.GetWorldMatrix(_transform, tmp);
|
||||
Matrix::RotationY(PI * -0.5f, rot);
|
||||
Matrix::Multiply(rot, tmp, world);
|
||||
GeometryDrawStateData drawState;
|
||||
Mesh::DrawInfo draw;
|
||||
draw.Buffer = &_previewModelBuffer;
|
||||
draw.World = &world;
|
||||
draw.DrawState = &drawState;
|
||||
draw.Flags = StaticFlags::Transform;
|
||||
draw.DrawModes = (DrawPass::Depth | DrawPass::GBuffer | DrawPass::Forward) & renderContext.View.Pass;
|
||||
BoundingSphere::FromBox(_previewModelBox, draw.Bounds);
|
||||
|
||||
@@ -8,12 +8,14 @@
|
||||
#include "Engine/Graphics/GPUBufferDescription.h"
|
||||
#include "Engine/Graphics/GPUContext.h"
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
#include "Engine/Graphics/RenderBuffers.h"
|
||||
#include "Engine/Graphics/RenderTask.h"
|
||||
#include "Engine/Graphics/Models/MeshDeformation.h"
|
||||
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
|
||||
#include "Engine/Serialization/Serialization.h"
|
||||
#include "Engine/Level/Prefabs/PrefabManager.h"
|
||||
#include "Engine/Level/Scene/Scene.h"
|
||||
#include "Engine/Renderer/DrawCall.h"
|
||||
#include "Engine/Renderer/GlobalSignDistanceFieldPass.h"
|
||||
#include "Engine/Renderer/GI/GlobalSurfaceAtlasPass.h"
|
||||
#include "Engine/Utilities/Encryption.h"
|
||||
@@ -380,15 +382,16 @@ void StaticModel::Draw(RenderContext& renderContext)
|
||||
GlobalSurfaceAtlasPass::Instance()->RasterizeActor(this, this, _sphere, _transform, Model->LODs.Last().GetBox());
|
||||
return;
|
||||
}
|
||||
auto drawState = renderContext.Buffers->GetGeometryDrawState(&GetScene()->Rendering, _sceneRenderingKey, this);
|
||||
ACTOR_GET_WORLD_MATRIX(this, view, world);
|
||||
GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world);
|
||||
GEOMETRY_DRAW_STATE_EVENT_BEGIN(drawState, world);
|
||||
if (_vertexColorsDirty)
|
||||
FlushVertexColors();
|
||||
|
||||
Mesh::DrawInfo draw;
|
||||
draw.Buffer = &Entries;
|
||||
draw.World = &world;
|
||||
draw.DrawState = &_drawState;
|
||||
draw.DrawState = drawState;
|
||||
draw.Deformation = _deformation;
|
||||
draw.Lightmap = _scene && Lightmap.TextureIndex != -1 ? _scene->LightmapsData.GetReadyLightmap(Lightmap.TextureIndex) : nullptr;
|
||||
draw.LightmapUVs = &Lightmap.UVsArea;
|
||||
@@ -409,7 +412,7 @@ void StaticModel::Draw(RenderContext& renderContext)
|
||||
|
||||
Model->Draw(renderContext, draw);
|
||||
|
||||
GEOMETRY_DRAW_STATE_EVENT_END(_drawState, world);
|
||||
GEOMETRY_DRAW_STATE_EVENT_END(drawState, world);
|
||||
}
|
||||
|
||||
void StaticModel::Draw(RenderContextBatch& renderContextBatch)
|
||||
@@ -417,15 +420,16 @@ void StaticModel::Draw(RenderContextBatch& renderContextBatch)
|
||||
if (!Model || !Model->IsLoaded())
|
||||
return;
|
||||
const RenderContext& renderContext = renderContextBatch.GetMainContext();
|
||||
auto drawState = renderContext.Buffers->GetGeometryDrawState(&GetScene()->Rendering, _sceneRenderingKey, this);
|
||||
ACTOR_GET_WORLD_MATRIX(this, view, world);
|
||||
GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world);
|
||||
GEOMETRY_DRAW_STATE_EVENT_BEGIN(drawState, world);
|
||||
if (_vertexColorsDirty)
|
||||
FlushVertexColors();
|
||||
|
||||
Mesh::DrawInfo draw;
|
||||
draw.Buffer = &Entries;
|
||||
draw.World = &world;
|
||||
draw.DrawState = &_drawState;
|
||||
draw.DrawState = drawState;
|
||||
draw.Deformation = _deformation;
|
||||
draw.Lightmap = _scene && Lightmap.TextureIndex != -1 ? _scene->LightmapsData.GetReadyLightmap(Lightmap.TextureIndex) : nullptr;
|
||||
draw.LightmapUVs = &Lightmap.UVsArea;
|
||||
@@ -446,7 +450,7 @@ void StaticModel::Draw(RenderContextBatch& renderContextBatch)
|
||||
|
||||
Model->Draw(renderContextBatch, draw);
|
||||
|
||||
GEOMETRY_DRAW_STATE_EVENT_END(_drawState, world);
|
||||
GEOMETRY_DRAW_STATE_EVENT_END(drawState, world);
|
||||
}
|
||||
|
||||
bool StaticModel::IntersectsItself(const Ray& ray, Real& distance, Vector3& normal)
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include "ModelInstanceActor.h"
|
||||
#include "Engine/Content/Assets/Model.h"
|
||||
#include "Engine/Renderer/DrawCall.h"
|
||||
#include "Engine/Renderer/Lightmaps.h"
|
||||
|
||||
/// <summary>
|
||||
@@ -15,15 +14,14 @@ class FLAXENGINE_API StaticModel : public ModelInstanceActor, IAssetReference
|
||||
{
|
||||
DECLARE_SCENE_OBJECT(StaticModel);
|
||||
private:
|
||||
GeometryDrawStateData _drawState;
|
||||
float _scaleInLightmap;
|
||||
float _boundsScale;
|
||||
DrawPass _drawModes = DrawPass::Default;
|
||||
char _lodBias;
|
||||
char _forcedLod;
|
||||
bool _vertexColorsDirty;
|
||||
byte _vertexColorsCount;
|
||||
int8 _sortOrder;
|
||||
DrawPass _drawModes = DrawPass::Default;
|
||||
Array<Color32> _vertexColorsData[MODEL_MAX_LODS];
|
||||
GPUBuffer* _vertexColorsBuffer[MODEL_MAX_LODS];
|
||||
Model* _residencyChangedModel = nullptr;
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||
|
||||
// Enable to put CPU profiler sections for each actor drawing to inspect slow actors draw issues
|
||||
#define SCENE_RENDERING_USE_PROFILER_PER_ACTOR 0
|
||||
|
||||
#include "SceneRendering.h"
|
||||
#include "Engine/Graphics/RenderTask.h"
|
||||
#include "Engine/Graphics/RenderView.h"
|
||||
#include "Engine/Renderer/RenderList.h"
|
||||
#include "Engine/Graphics/RenderBuffers.h"
|
||||
#include "Engine/Threading/JobSystem.h"
|
||||
#include "Engine/Physics/Actors/IPhysicsDebug.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
@@ -38,6 +40,7 @@ void ISceneRenderingListener::ListenSceneRendering(SceneRendering* scene)
|
||||
{
|
||||
if (!_scenes.Contains(scene))
|
||||
{
|
||||
PROFILE_MEM(Graphics);
|
||||
_scenes.Add(scene);
|
||||
scene->_listeners.Add(this);
|
||||
}
|
||||
@@ -67,6 +70,8 @@ void SceneRendering::Draw(RenderContextBatch& renderContextBatch, DrawCategory c
|
||||
// Register scene
|
||||
for (const auto& renderContext : renderContextBatch.Contexts)
|
||||
renderContext.List->Scenes.Add(this);
|
||||
auto buffers = renderContextBatch.GetMainContext().Buffers;
|
||||
buffers->OnSceneRendering(this);
|
||||
}
|
||||
else if (category == PostRender)
|
||||
{
|
||||
@@ -188,7 +193,7 @@ void SceneRendering::AddActor(Actor* a, int32& key)
|
||||
e.Bounds = a->GetSphere();
|
||||
e.NoCulling = a->_drawNoCulling;
|
||||
for (auto* listener : _listeners)
|
||||
listener->OnSceneRenderingAddActor(a);
|
||||
listener->OnSceneRenderingAddActor(this, key, a);
|
||||
}
|
||||
|
||||
void SceneRendering::UpdateActor(Actor* a, int32& key, ISceneRenderingListener::UpdateFlags flags)
|
||||
@@ -204,7 +209,7 @@ void SceneRendering::UpdateActor(Actor* a, int32& key, ISceneRenderingListener::
|
||||
if (e.Actor == a)
|
||||
{
|
||||
for (auto* listener : _listeners)
|
||||
listener->OnSceneRenderingUpdateActor(a, e.Bounds, flags);
|
||||
listener->OnSceneRenderingUpdateActor(this, key, a, e.Bounds, flags);
|
||||
if (flags & ISceneRenderingListener::Layer)
|
||||
e.LayerMask = a->GetLayerMask();
|
||||
if (flags & ISceneRenderingListener::Bounds)
|
||||
@@ -227,7 +232,7 @@ void SceneRendering::RemoveActor(Actor* a, int32& key)
|
||||
if (e.Actor == a)
|
||||
{
|
||||
for (auto* listener : _listeners)
|
||||
listener->OnSceneRenderingRemoveActor(a);
|
||||
listener->OnSceneRenderingRemoveActor(this, key, a);
|
||||
e.Actor = nullptr;
|
||||
e.LayerMask = 0;
|
||||
FreeActors[category].Add(key);
|
||||
|
||||
@@ -51,22 +51,22 @@ public:
|
||||
// Actor properties that were modified.
|
||||
enum UpdateFlags
|
||||
{
|
||||
Visual = 1,
|
||||
Bounds = 2,
|
||||
Layer = 4,
|
||||
StaticFlags = 8,
|
||||
AutoDelayDuringRendering = 16, // Conditionally allow updating data during rendering when writes are locked
|
||||
DrawModes = 32,
|
||||
Auto = Visual | Bounds | Layer,
|
||||
Visual = 1, // Visual appearance of the object (eg. material changed).
|
||||
Bounds = 2, // Object bounding volume was changed (eg. after scaling).
|
||||
Layer = 4, // Object changed layer.
|
||||
StaticFlags = 8, // Object changed static state.
|
||||
AutoDelayDuringRendering = 16, // Conditionally allow updating data during rendering when writes are locked.
|
||||
DrawModes = 32, // Object changed draw modes flags.
|
||||
Auto = Visual | Bounds | Layer, // Default set of flags for common changes.
|
||||
};
|
||||
|
||||
// Starts listening to the scene rendering events.
|
||||
void ListenSceneRendering(SceneRendering* scene);
|
||||
|
||||
// Events called by Scene Rendering
|
||||
virtual void OnSceneRenderingAddActor(Actor* a) = 0;
|
||||
virtual void OnSceneRenderingUpdateActor(Actor* a, const BoundingSphere& prevBounds, UpdateFlags flags = Auto) = 0;
|
||||
virtual void OnSceneRenderingRemoveActor(Actor* a) = 0;
|
||||
virtual void OnSceneRenderingAddActor(SceneRendering* scene, int32 key, Actor* a) = 0;
|
||||
virtual void OnSceneRenderingUpdateActor(SceneRendering* scene, int32 key, Actor* a, const BoundingSphere& prevBounds, UpdateFlags flags = Auto) = 0;
|
||||
virtual void OnSceneRenderingRemoveActor(SceneRendering* scene, int32 key, Actor* a) = 0;
|
||||
virtual void OnSceneRenderingClear(SceneRendering* scene) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -322,7 +322,7 @@ struct TIsPODType<DrawCall>
|
||||
/// Data container for meshes and skinned meshes rendering with minimal state caching.
|
||||
/// Used to update previous world transformation matrix for motion vectors pass and handle LOD transitions blending.
|
||||
/// </summary>
|
||||
struct GeometryDrawStateData
|
||||
struct GeometryDrawState
|
||||
{
|
||||
/// <summary>
|
||||
/// The previous frame world transformation matrix for the given geometry instance.
|
||||
@@ -347,23 +347,23 @@ struct GeometryDrawStateData
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TIsPODType<GeometryDrawStateData>
|
||||
struct TIsPODType<GeometryDrawState>
|
||||
{
|
||||
enum { Value = true };
|
||||
};
|
||||
|
||||
#define GEOMETRY_DRAW_STATE_EVENT_BEGIN(drawState, worldMatrix) \
|
||||
const auto frame = Engine::FrameCount; \
|
||||
if (drawState.PrevFrame + 1 < frame && !renderContext.View.IsSingleFrame) \
|
||||
if (drawState && drawState->PrevFrame + 1 < frame && !renderContext.View.IsSingleFrame) \
|
||||
{ \
|
||||
drawState.PrevWorld = worldMatrix; \
|
||||
drawState->PrevWorld = worldMatrix; \
|
||||
}
|
||||
|
||||
#define GEOMETRY_DRAW_STATE_EVENT_END(drawState, worldMatrix) \
|
||||
if (drawState.PrevFrame != frame && !renderContext.View.IsSingleFrame) \
|
||||
if (drawState && drawState->PrevFrame != frame && !renderContext.View.IsSingleFrame) \
|
||||
{ \
|
||||
drawState.PrevWorld = worldMatrix; \
|
||||
drawState.PrevFrame = frame; \
|
||||
drawState->PrevWorld = worldMatrix; \
|
||||
drawState->PrevFrame = frame; \
|
||||
}
|
||||
|
||||
#if USE_LARGE_WORLDS
|
||||
|
||||
@@ -716,11 +716,11 @@ public:
|
||||
}
|
||||
|
||||
// [ISceneRenderingListener]
|
||||
void OnSceneRenderingAddActor(Actor* a) override
|
||||
void OnSceneRenderingAddActor(SceneRendering* scene, int32 key, Actor* a) override
|
||||
{
|
||||
}
|
||||
|
||||
void OnSceneRenderingUpdateActor(Actor* a, const BoundingSphere& prevBounds, UpdateFlags flags) override
|
||||
void OnSceneRenderingUpdateActor(SceneRendering* scene, int32 key, Actor* a, const BoundingSphere& prevBounds, UpdateFlags flags) override
|
||||
{
|
||||
GlobalSurfaceAtlasObject* object = Objects.TryGet(a);
|
||||
if (object)
|
||||
@@ -744,7 +744,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void OnSceneRenderingRemoveActor(Actor* a) override
|
||||
void OnSceneRenderingRemoveActor(SceneRendering* scene, int32 key, Actor* a) override
|
||||
{
|
||||
// TODO: use it to speed up atlas/buffers defragmentation when streaming out scenes (CompactObjects cleans up objects)
|
||||
}
|
||||
|
||||
@@ -475,17 +475,17 @@ public:
|
||||
}
|
||||
|
||||
// [ISceneRenderingListener]
|
||||
void OnSceneRenderingAddActor(Actor* a) override
|
||||
void OnSceneRenderingAddActor(SceneRendering* scene, int32 key, Actor* a) override
|
||||
{
|
||||
OnSceneRenderingDirty(a);
|
||||
}
|
||||
|
||||
void OnSceneRenderingUpdateActor(Actor* a, const BoundingSphere& prevBounds, UpdateFlags flags) override
|
||||
void OnSceneRenderingUpdateActor(SceneRendering* scene, int32 key, Actor* a, const BoundingSphere& prevBounds, UpdateFlags flags) override
|
||||
{
|
||||
OnSceneRenderingDirty(a, &prevBounds, flags);
|
||||
}
|
||||
|
||||
void OnSceneRenderingRemoveActor(Actor* a) override
|
||||
void OnSceneRenderingRemoveActor(SceneRendering* scene, int32 key, Actor* a) override
|
||||
{
|
||||
OnSceneRenderingDirty(a);
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ struct RenderListAlloc
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Rendering cache container object for the draw calls collecting, sorting and executing.
|
||||
/// Rendering cache container object for the draw calls collecting, sorting and executing. Reusable between frames or drawing tasks.
|
||||
/// </summary>
|
||||
API_CLASS(Sealed) class FLAXENGINE_API RenderList : public ScriptingObject
|
||||
{
|
||||
|
||||
@@ -409,13 +409,13 @@ public:
|
||||
}
|
||||
|
||||
// [ISceneRenderingListener]
|
||||
void OnSceneRenderingAddActor(Actor* a) override
|
||||
void OnSceneRenderingAddActor(SceneRendering* scene, int32 key, Actor* a) override
|
||||
{
|
||||
if (a->HasStaticFlag(StaticFlags::Shadow))
|
||||
DirtyStaticBounds(a->GetSphere());
|
||||
}
|
||||
|
||||
void OnSceneRenderingUpdateActor(Actor* a, const BoundingSphere& prevBounds, UpdateFlags flags) override
|
||||
void OnSceneRenderingUpdateActor(SceneRendering* scene, int32 key, Actor* a, const BoundingSphere& prevBounds, UpdateFlags flags) override
|
||||
{
|
||||
// Dirty static objects to redraw when changed (eg. material modification)
|
||||
if (a->HasStaticFlag(StaticFlags::Shadow))
|
||||
@@ -438,7 +438,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void OnSceneRenderingRemoveActor(Actor* a) override
|
||||
void OnSceneRenderingRemoveActor(SceneRendering* scene, int32 key, Actor* a) override
|
||||
{
|
||||
if (a->HasStaticFlag(StaticFlags::Shadow))
|
||||
DirtyStaticBounds(a->GetSphere());
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "Engine/Core/Types/TimeSpan.h"
|
||||
#include "Engine/Engine/Engine.h"
|
||||
#include "Engine/Renderer/Renderer.h"
|
||||
#include "Engine/Renderer/DrawCall.h"
|
||||
#include "Engine/Renderer/Lightmaps.h"
|
||||
#include "Engine/Level/Scene/Lightmap.h"
|
||||
#include "Engine/Level/Actors/StaticModel.h"
|
||||
#include "Engine/Level/Actors/BoxBrush.h"
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
#include "Engine/Graphics/Models/Types.h"
|
||||
#include "Engine/Graphics/RenderView.h"
|
||||
#include "Engine/Graphics/RenderTask.h"
|
||||
#include "Engine/Level/Scene/SceneRendering.h"
|
||||
#include "Engine/Graphics/RenderBuffers.h"
|
||||
#include "Engine/Graphics/RenderTools.h"
|
||||
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
|
||||
#include "Engine/Render2D/Font.h"
|
||||
#include "Engine/Render2D/FontAsset.h"
|
||||
#include "Engine/Render2D/FontManager.h"
|
||||
@@ -20,8 +22,8 @@
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "Engine/Content/Deprecated.h"
|
||||
#include "Engine/Core/Types/Variant.h"
|
||||
#include "Engine/Graphics/RenderTools.h"
|
||||
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
|
||||
#include "Engine/Level/Scene/Scene.h"
|
||||
#include "Engine/Level/Scene/SceneRendering.h"
|
||||
#include "Engine/Localization/Localization.h"
|
||||
#if USE_EDITOR
|
||||
#include "Editor/Editor.h"
|
||||
@@ -370,7 +372,8 @@ void TextRender::Draw(RenderContext& renderContext)
|
||||
UpdateLayout();
|
||||
Matrix world;
|
||||
renderContext.View.GetWorldMatrix(_transform, world);
|
||||
GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world);
|
||||
auto drawState = renderContext.Buffers->GetGeometryDrawState(&GetScene()->Rendering, _sceneRenderingKey, this);
|
||||
GEOMETRY_DRAW_STATE_EVENT_BEGIN(drawState, world);
|
||||
|
||||
const DrawPass drawModes = DrawModes & renderContext.View.Pass & renderContext.View.GetShadowsDrawPassMask(ShadowsMode);
|
||||
if (_vb.Data.Count() > 0 && drawModes != DrawPass::None)
|
||||
@@ -389,7 +392,7 @@ void TextRender::Draw(RenderContext& renderContext)
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = (float)_sphere.Radius;
|
||||
drawCall.Surface.GeometrySize = _localBox.GetSize();
|
||||
drawCall.Surface.PrevWorld = _drawState.PrevWorld;
|
||||
drawCall.Surface.PrevWorld = drawState ? drawState->PrevWorld : world;
|
||||
drawCall.PerInstanceRandom = GetPerInstanceRandom();
|
||||
drawCall.SetStencilValue(_layer);
|
||||
drawCall.Geometry.IndexBuffer = _ib.GetBuffer();
|
||||
@@ -409,7 +412,7 @@ void TextRender::Draw(RenderContext& renderContext)
|
||||
}
|
||||
}
|
||||
|
||||
GEOMETRY_DRAW_STATE_EVENT_END(_drawState, world);
|
||||
GEOMETRY_DRAW_STATE_EVENT_END(drawState, world);
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
@@ -42,7 +42,6 @@ private:
|
||||
int32 _sceneRenderingKey = -1;
|
||||
|
||||
BoundingBox _localBox;
|
||||
GeometryDrawStateData _drawState;
|
||||
DynamicIndexBuffer _ib;
|
||||
DynamicVertexBuffer _vb;
|
||||
#if MODEL_USE_PRECISE_MESH_INTERSECTS
|
||||
|
||||
Reference in New Issue
Block a user