Optimize Global Surface Atlas objects lighting to be less frequent with caching for static lights and objects
This commit is contained in:
@@ -41,6 +41,8 @@ void DirectionalLight::Draw(RenderContext& renderContext)
|
|||||||
data.ShadowsMode = ShadowsMode;
|
data.ShadowsMode = ShadowsMode;
|
||||||
data.CascadeCount = CascadeCount;
|
data.CascadeCount = CascadeCount;
|
||||||
data.ContactShadowsLength = ContactShadowsLength;
|
data.ContactShadowsLength = ContactShadowsLength;
|
||||||
|
data.StaticFlags = GetStaticFlags();
|
||||||
|
data.ID = GetID();
|
||||||
renderContext.List->DirectionalLights.Add(data);
|
renderContext.List->DirectionalLights.Add(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,6 +133,8 @@ void PointLight::Draw(RenderContext& renderContext)
|
|||||||
data.ContactShadowsLength = ContactShadowsLength;
|
data.ContactShadowsLength = ContactShadowsLength;
|
||||||
data.IndirectLightingIntensity = IndirectLightingIntensity;
|
data.IndirectLightingIntensity = IndirectLightingIntensity;
|
||||||
data.IESTexture = IESTexture ? IESTexture->GetTexture() : nullptr;
|
data.IESTexture = IESTexture ? IESTexture->GetTexture() : nullptr;
|
||||||
|
data.StaticFlags = GetStaticFlags();
|
||||||
|
data.ID = GetID();
|
||||||
renderContext.List->PointLights.Add(data);
|
renderContext.List->PointLights.Add(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,6 +115,8 @@ void SkyLight::Draw(RenderContext& renderContext)
|
|||||||
data.IndirectLightingIntensity = IndirectLightingIntensity;
|
data.IndirectLightingIntensity = IndirectLightingIntensity;
|
||||||
data.Radius = GetScaledRadius();
|
data.Radius = GetScaledRadius();
|
||||||
data.Image = GetSource();
|
data.Image = GetSource();
|
||||||
|
data.StaticFlags = GetStaticFlags();
|
||||||
|
data.ID = GetID();
|
||||||
renderContext.List->SkyLights.Add(data);
|
renderContext.List->SkyLights.Add(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,6 +186,8 @@ void SpotLight::Draw(RenderContext& renderContext)
|
|||||||
data.IESTexture = IESTexture ? IESTexture->GetTexture() : nullptr;
|
data.IESTexture = IESTexture ? IESTexture->GetTexture() : nullptr;
|
||||||
Float3::Transform(Float3::Up, GetOrientation(), data.UpVector);
|
Float3::Transform(Float3::Up, GetOrientation(), data.UpVector);
|
||||||
data.OuterConeAngle = outerConeAngle;
|
data.OuterConeAngle = outerConeAngle;
|
||||||
|
data.StaticFlags = GetStaticFlags();
|
||||||
|
data.ID = GetID();
|
||||||
renderContext.List->SpotLights.Add(data);
|
renderContext.List->SpotLights.Add(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,8 @@ struct GlobalSurfaceAtlasTile : RectPack<GlobalSurfaceAtlasTile, uint16>
|
|||||||
struct GlobalSurfaceAtlasObject
|
struct GlobalSurfaceAtlasObject
|
||||||
{
|
{
|
||||||
uint64 LastFrameUsed;
|
uint64 LastFrameUsed;
|
||||||
uint64 LastFrameDirty;
|
uint64 LastFrameUpdated;
|
||||||
|
uint64 LightingUpdateFrame; // Index of the frame to update lighting for this object (calculated when object gets dirty or overriden by dynamic lights)
|
||||||
Actor* Actor;
|
Actor* Actor;
|
||||||
GlobalSurfaceAtlasTile* Tiles[6];
|
GlobalSurfaceAtlasTile* Tiles[6];
|
||||||
float Radius;
|
float Radius;
|
||||||
@@ -120,6 +121,12 @@ struct GlobalSurfaceAtlasObject
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GlobalSurfaceAtlasLight
|
||||||
|
{
|
||||||
|
uint64 LastFrameUsed = 0;
|
||||||
|
uint64 LastFrameUpdated = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class GlobalSurfaceAtlasCustomBuffer : public RenderBuffers::CustomBuffer, public ISceneRenderingListener
|
class GlobalSurfaceAtlasCustomBuffer : public RenderBuffers::CustomBuffer, public ISceneRenderingListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -139,6 +146,7 @@ public:
|
|||||||
GlobalSurfaceAtlasPass::BindingData Result;
|
GlobalSurfaceAtlasPass::BindingData Result;
|
||||||
GlobalSurfaceAtlasTile* AtlasTiles = nullptr; // TODO: optimize with a single allocation for atlas tiles
|
GlobalSurfaceAtlasTile* AtlasTiles = nullptr; // TODO: optimize with a single allocation for atlas tiles
|
||||||
Dictionary<void*, GlobalSurfaceAtlasObject> Objects;
|
Dictionary<void*, GlobalSurfaceAtlasObject> Objects;
|
||||||
|
Dictionary<Guid, GlobalSurfaceAtlasLight> Lights;
|
||||||
|
|
||||||
// Cached data to be reused during RasterizeActor
|
// Cached data to be reused during RasterizeActor
|
||||||
uint64 CurrentFrame;
|
uint64 CurrentFrame;
|
||||||
@@ -160,6 +168,7 @@ public:
|
|||||||
LastFrameAtlasDefragmentation = Engine::FrameCount;
|
LastFrameAtlasDefragmentation = Engine::FrameCount;
|
||||||
SAFE_DELETE(AtlasTiles);
|
SAFE_DELETE(AtlasTiles);
|
||||||
Objects.Clear();
|
Objects.Clear();
|
||||||
|
Lights.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE void Clear()
|
FORCE_INLINE void Clear()
|
||||||
@@ -194,7 +203,13 @@ public:
|
|||||||
if (object)
|
if (object)
|
||||||
{
|
{
|
||||||
// Dirty object to redraw
|
// Dirty object to redraw
|
||||||
object->LastFrameDirty = 0;
|
object->LastFrameUpdated = 0;
|
||||||
|
}
|
||||||
|
GlobalSurfaceAtlasLight* light = Lights.TryGet(a->GetID());
|
||||||
|
if (light)
|
||||||
|
{
|
||||||
|
// Dirty light to redraw
|
||||||
|
light->LastFrameUpdated = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -271,12 +286,20 @@ bool GlobalSurfaceAtlasPass::setupResources()
|
|||||||
if (_psClear->Init(psDesc))
|
if (_psClear->Init(psDesc))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
psDesc.DepthTestEnable = false;
|
||||||
|
psDesc.DepthWriteEnable = false;
|
||||||
|
psDesc.DepthFunc = ComparisonFunc::Never;
|
||||||
|
if (!_psClearLighting)
|
||||||
|
{
|
||||||
|
_psClearLighting = device->CreatePipelineState();
|
||||||
|
psDesc.VS = shader->GetVS("VS_Atlas");
|
||||||
|
psDesc.PS = shader->GetPS("PS_ClearLighting");
|
||||||
|
if (_psClearLighting->Init(psDesc))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (!_psDirectLighting0)
|
if (!_psDirectLighting0)
|
||||||
{
|
{
|
||||||
_psDirectLighting0 = device->CreatePipelineState();
|
_psDirectLighting0 = device->CreatePipelineState();
|
||||||
psDesc.DepthTestEnable = false;
|
|
||||||
psDesc.DepthWriteEnable = false;
|
|
||||||
psDesc.DepthFunc = ComparisonFunc::Never;
|
|
||||||
psDesc.BlendMode = BlendingMode::Add;
|
psDesc.BlendMode = BlendingMode::Add;
|
||||||
psDesc.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::RGB;
|
psDesc.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::RGB;
|
||||||
psDesc.PS = shader->GetPS("PS_Lighting", 0);
|
psDesc.PS = shader->GetPS("PS_Lighting", 0);
|
||||||
@@ -300,6 +323,7 @@ bool GlobalSurfaceAtlasPass::setupResources()
|
|||||||
void GlobalSurfaceAtlasPass::OnShaderReloading(Asset* obj)
|
void GlobalSurfaceAtlasPass::OnShaderReloading(Asset* obj)
|
||||||
{
|
{
|
||||||
SAFE_DELETE_GPU_RESOURCE(_psClear);
|
SAFE_DELETE_GPU_RESOURCE(_psClear);
|
||||||
|
SAFE_DELETE_GPU_RESOURCE(_psClearLighting);
|
||||||
SAFE_DELETE_GPU_RESOURCE(_psDirectLighting0);
|
SAFE_DELETE_GPU_RESOURCE(_psDirectLighting0);
|
||||||
SAFE_DELETE_GPU_RESOURCE(_psDirectLighting1);
|
SAFE_DELETE_GPU_RESOURCE(_psDirectLighting1);
|
||||||
SAFE_DELETE_GPU_RESOURCE(_psIndirectLighting);
|
SAFE_DELETE_GPU_RESOURCE(_psIndirectLighting);
|
||||||
@@ -317,6 +341,7 @@ void GlobalSurfaceAtlasPass::Dispose()
|
|||||||
SAFE_DELETE(_vertexBuffer);
|
SAFE_DELETE(_vertexBuffer);
|
||||||
SAFE_DELETE_GPU_RESOURCE(_culledObjectsSizeBuffer);
|
SAFE_DELETE_GPU_RESOURCE(_culledObjectsSizeBuffer);
|
||||||
SAFE_DELETE_GPU_RESOURCE(_psClear);
|
SAFE_DELETE_GPU_RESOURCE(_psClear);
|
||||||
|
SAFE_DELETE_GPU_RESOURCE(_psClearLighting);
|
||||||
SAFE_DELETE_GPU_RESOURCE(_psDirectLighting0);
|
SAFE_DELETE_GPU_RESOURCE(_psDirectLighting0);
|
||||||
SAFE_DELETE_GPU_RESOURCE(_psDirectLighting1);
|
SAFE_DELETE_GPU_RESOURCE(_psDirectLighting1);
|
||||||
SAFE_DELETE_GPU_RESOURCE(_psIndirectLighting);
|
SAFE_DELETE_GPU_RESOURCE(_psIndirectLighting);
|
||||||
@@ -744,14 +769,6 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
|||||||
if (surfaceAtlasData.Objects.Count() != 0)
|
if (surfaceAtlasData.Objects.Count() != 0)
|
||||||
{
|
{
|
||||||
PROFILE_GPU_CPU("Direct Lighting");
|
PROFILE_GPU_CPU("Direct Lighting");
|
||||||
|
|
||||||
// Copy emissive light into the final direct lighting atlas
|
|
||||||
// TODO: test perf diff when manually copying only dirty object tiles and dirty light tiles together with indirect lighting
|
|
||||||
{
|
|
||||||
PROFILE_GPU_CPU("Copy Emissive");
|
|
||||||
context->CopyTexture(surfaceAtlasData.AtlasLighting, 0, 0, 0, 0, surfaceAtlasData.AtlasEmissive, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
context->SetViewportAndScissors(Viewport(0, 0, (float)resolution, (float)resolution));
|
context->SetViewportAndScissors(Viewport(0, 0, (float)resolution, (float)resolution));
|
||||||
context->SetRenderTarget(surfaceAtlasData.AtlasLighting->View());
|
context->SetRenderTarget(surfaceAtlasData.AtlasLighting->View());
|
||||||
context->BindSR(0, surfaceAtlasData.AtlasGBuffer0->View());
|
context->BindSR(0, surfaceAtlasData.AtlasGBuffer0->View());
|
||||||
@@ -767,8 +784,114 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
|||||||
data.GlobalSDF = bindingDataSDF.Constants;
|
data.GlobalSDF = bindingDataSDF.Constants;
|
||||||
data.GlobalSurfaceAtlas = result.Constants;
|
data.GlobalSurfaceAtlas = result.Constants;
|
||||||
|
|
||||||
|
// Collect objects to update lighting this frame (dirty objects and dirty lights)
|
||||||
|
bool allLightingDirty = false;
|
||||||
|
for (auto& light : renderContext.List->DirectionalLights)
|
||||||
|
{
|
||||||
|
GlobalSurfaceAtlasLight& lightData = surfaceAtlasData.Lights[light.ID];
|
||||||
|
lightData.LastFrameUsed = currentFrame;
|
||||||
|
uint32 redrawFramesCount = (light.StaticFlags & StaticFlags::Lightmap) ? 120 : 4;
|
||||||
|
if (surfaceAtlasData.CurrentFrame - lightData.LastFrameUpdated < (redrawFramesCount + (light.ID.D & redrawFramesCount)))
|
||||||
|
continue;
|
||||||
|
lightData.LastFrameUpdated = currentFrame;
|
||||||
|
|
||||||
|
// Mark all objects to shade
|
||||||
|
allLightingDirty = true;
|
||||||
|
}
|
||||||
|
if (renderContext.View.Flags & ViewFlags::GI && (renderContext.List->DirectionalLights.Count() != 1 || renderContext.List->DirectionalLights[0].StaticFlags & StaticFlags::Lightmap))
|
||||||
|
{
|
||||||
|
switch (renderContext.List->Settings.GlobalIllumination.Mode)
|
||||||
|
{
|
||||||
|
case GlobalIlluminationMode::DDGI:
|
||||||
|
{
|
||||||
|
DynamicDiffuseGlobalIlluminationPass::BindingData bindingDataDDGI;
|
||||||
|
if (!DynamicDiffuseGlobalIlluminationPass::Instance()->Get(renderContext.Buffers, bindingDataDDGI))
|
||||||
|
{
|
||||||
|
GlobalSurfaceAtlasLight& lightData = surfaceAtlasData.Lights[Guid(0, 0, 0, 1)];
|
||||||
|
lightData.LastFrameUsed = currentFrame;
|
||||||
|
uint32 redrawFramesCount = 4; // GI Bounce redraw minimum frequency
|
||||||
|
if (surfaceAtlasData.CurrentFrame - lightData.LastFrameUpdated < redrawFramesCount)
|
||||||
|
break;
|
||||||
|
lightData.LastFrameUpdated = currentFrame;
|
||||||
|
|
||||||
|
// Mark all objects to shade
|
||||||
|
allLightingDirty = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto& light : renderContext.List->PointLights)
|
||||||
|
{
|
||||||
|
GlobalSurfaceAtlasLight& lightData = surfaceAtlasData.Lights[light.ID];
|
||||||
|
lightData.LastFrameUsed = currentFrame;
|
||||||
|
uint32 redrawFramesCount = (light.StaticFlags & StaticFlags::Lightmap) ? 120 : 4;
|
||||||
|
if (surfaceAtlasData.CurrentFrame - lightData.LastFrameUpdated < (redrawFramesCount + (light.ID.D & redrawFramesCount)))
|
||||||
|
continue;
|
||||||
|
lightData.LastFrameUpdated = currentFrame;
|
||||||
|
|
||||||
|
if (!allLightingDirty)
|
||||||
|
{
|
||||||
|
// Mark objects to shade
|
||||||
|
for (auto& e : surfaceAtlasData.Objects)
|
||||||
|
{
|
||||||
|
auto& object = e.Value;
|
||||||
|
Float3 lightToObject = object.Bounds.GetCenter() - light.Position;
|
||||||
|
if (lightToObject.LengthSquared() >= Math::Square(object.Radius + light.Radius))
|
||||||
|
continue;
|
||||||
|
object.LightingUpdateFrame = currentFrame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto& light : renderContext.List->SpotLights)
|
||||||
|
{
|
||||||
|
GlobalSurfaceAtlasLight& lightData = surfaceAtlasData.Lights[light.ID];
|
||||||
|
lightData.LastFrameUsed = currentFrame;
|
||||||
|
uint32 redrawFramesCount = (light.StaticFlags & StaticFlags::Lightmap) ? 120 : 4;
|
||||||
|
if (surfaceAtlasData.CurrentFrame - lightData.LastFrameUpdated < (redrawFramesCount + (light.ID.D & redrawFramesCount)))
|
||||||
|
continue;
|
||||||
|
lightData.LastFrameUpdated = currentFrame;
|
||||||
|
|
||||||
|
if (!allLightingDirty)
|
||||||
|
{
|
||||||
|
// Mark objects to shade
|
||||||
|
for (auto& e : surfaceAtlasData.Objects)
|
||||||
|
{
|
||||||
|
auto& object = e.Value;
|
||||||
|
Float3 lightToObject = object.Bounds.GetCenter() - light.Position;
|
||||||
|
if (lightToObject.LengthSquared() >= Math::Square(object.Radius + light.Radius))
|
||||||
|
continue;
|
||||||
|
object.LightingUpdateFrame = currentFrame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy emissive light into the final direct lighting atlas
|
||||||
|
{
|
||||||
|
PROFILE_GPU_CPU("Copy Emissive");
|
||||||
|
_vertexBuffer->Clear();
|
||||||
|
for (const auto& e : surfaceAtlasData.Objects)
|
||||||
|
{
|
||||||
|
const auto& object = e.Value;
|
||||||
|
if (!allLightingDirty && object.LightingUpdateFrame != currentFrame)
|
||||||
|
continue;
|
||||||
|
for (int32 tileIndex = 0; tileIndex < 6; tileIndex++)
|
||||||
|
{
|
||||||
|
auto* tile = object.Tiles[tileIndex];
|
||||||
|
if (!tile)
|
||||||
|
continue;
|
||||||
|
VB_WRITE_TILE(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_vertexBuffer->Data.Count() != 0)
|
||||||
|
{
|
||||||
|
context->BindSR(7, surfaceAtlasData.AtlasEmissive);
|
||||||
|
context->SetState(_psClearLighting);
|
||||||
|
VB_DRAW();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Shade object tiles influenced by lights to calculate direct lighting
|
// Shade object tiles influenced by lights to calculate direct lighting
|
||||||
// TODO: reduce redraw frequency for static lights (StaticFlags::Lightmap)
|
|
||||||
for (auto& light : renderContext.List->DirectionalLights)
|
for (auto& light : renderContext.List->DirectionalLights)
|
||||||
{
|
{
|
||||||
// Collect tiles to shade
|
// Collect tiles to shade
|
||||||
@@ -776,6 +899,8 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
|||||||
for (const auto& e : surfaceAtlasData.Objects)
|
for (const auto& e : surfaceAtlasData.Objects)
|
||||||
{
|
{
|
||||||
const auto& object = e.Value;
|
const auto& object = e.Value;
|
||||||
|
if (!allLightingDirty && object.LightingUpdateFrame != currentFrame)
|
||||||
|
continue;
|
||||||
for (int32 tileIndex = 0; tileIndex < 6; tileIndex++)
|
for (int32 tileIndex = 0; tileIndex < 6; tileIndex++)
|
||||||
{
|
{
|
||||||
auto* tile = object.Tiles[tileIndex];
|
auto* tile = object.Tiles[tileIndex];
|
||||||
@@ -784,8 +909,11 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
|||||||
VB_WRITE_TILE(tile);
|
VB_WRITE_TILE(tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_vertexBuffer->Data.Count() == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
// Draw draw light
|
// Draw draw light
|
||||||
|
PROFILE_GPU_CPU("Directional Light");
|
||||||
const bool useShadow = CanRenderShadow(renderContext.View, light);
|
const bool useShadow = CanRenderShadow(renderContext.View, light);
|
||||||
// TODO: test perf/quality when using Shadow Map for directional light (ShadowsPass::Instance()->LastDirLightShadowMap) instead of Global SDF trace
|
// TODO: test perf/quality when using Shadow Map for directional light (ShadowsPass::Instance()->LastDirLightShadowMap) instead of Global SDF trace
|
||||||
light.SetupLightData(&data.Light, useShadow);
|
light.SetupLightData(&data.Light, useShadow);
|
||||||
@@ -802,6 +930,8 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
|||||||
for (const auto& e : surfaceAtlasData.Objects)
|
for (const auto& e : surfaceAtlasData.Objects)
|
||||||
{
|
{
|
||||||
const auto& object = e.Value;
|
const auto& object = e.Value;
|
||||||
|
if (!allLightingDirty && object.LightingUpdateFrame != currentFrame)
|
||||||
|
continue;
|
||||||
Float3 lightToObject = object.Bounds.GetCenter() - light.Position;
|
Float3 lightToObject = object.Bounds.GetCenter() - light.Position;
|
||||||
if (lightToObject.LengthSquared() >= Math::Square(object.Radius + light.Radius))
|
if (lightToObject.LengthSquared() >= Math::Square(object.Radius + light.Radius))
|
||||||
continue;
|
continue;
|
||||||
@@ -813,8 +943,11 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
|||||||
VB_WRITE_TILE(tile);
|
VB_WRITE_TILE(tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_vertexBuffer->Data.Count() == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
// Draw draw light
|
// Draw draw light
|
||||||
|
PROFILE_GPU_CPU("Point Light");
|
||||||
const bool useShadow = CanRenderShadow(renderContext.View, light);
|
const bool useShadow = CanRenderShadow(renderContext.View, light);
|
||||||
light.SetupLightData(&data.Light, useShadow);
|
light.SetupLightData(&data.Light, useShadow);
|
||||||
data.Light.Color *= light.IndirectLightingIntensity;
|
data.Light.Color *= light.IndirectLightingIntensity;
|
||||||
@@ -830,6 +963,8 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
|||||||
for (const auto& e : surfaceAtlasData.Objects)
|
for (const auto& e : surfaceAtlasData.Objects)
|
||||||
{
|
{
|
||||||
const auto& object = e.Value;
|
const auto& object = e.Value;
|
||||||
|
if (!allLightingDirty && object.LightingUpdateFrame != currentFrame)
|
||||||
|
continue;
|
||||||
Float3 lightToObject = object.Bounds.GetCenter() - light.Position;
|
Float3 lightToObject = object.Bounds.GetCenter() - light.Position;
|
||||||
if (lightToObject.LengthSquared() >= Math::Square(object.Radius + light.Radius))
|
if (lightToObject.LengthSquared() >= Math::Square(object.Radius + light.Radius))
|
||||||
continue;
|
continue;
|
||||||
@@ -841,8 +976,11 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
|||||||
VB_WRITE_TILE(tile);
|
VB_WRITE_TILE(tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_vertexBuffer->Data.Count() == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
// Draw draw light
|
// Draw draw light
|
||||||
|
PROFILE_GPU_CPU("Spot Light");
|
||||||
const bool useShadow = CanRenderShadow(renderContext.View, light);
|
const bool useShadow = CanRenderShadow(renderContext.View, light);
|
||||||
light.SetupLightData(&data.Light, useShadow);
|
light.SetupLightData(&data.Light, useShadow);
|
||||||
data.Light.Color *= light.IndirectLightingIntensity;
|
data.Light.Color *= light.IndirectLightingIntensity;
|
||||||
@@ -851,9 +989,17 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
|||||||
context->SetState(_psDirectLighting1);
|
context->SetState(_psDirectLighting1);
|
||||||
VB_DRAW();
|
VB_DRAW();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove unused lights
|
||||||
|
for (auto it = surfaceAtlasData.Lights.Begin(); it.IsNotEnd(); ++it)
|
||||||
|
{
|
||||||
|
if (it->Value.LastFrameUsed != currentFrame)
|
||||||
|
surfaceAtlasData.Lights.Remove(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw draw indirect light from Global Illumination
|
||||||
if (renderContext.View.Flags & ViewFlags::GI)
|
if (renderContext.View.Flags & ViewFlags::GI)
|
||||||
{
|
{
|
||||||
// Draw draw indirect light from Global Illumination
|
|
||||||
switch (renderContext.List->Settings.GlobalIllumination.Mode)
|
switch (renderContext.List->Settings.GlobalIllumination.Mode)
|
||||||
{
|
{
|
||||||
case GlobalIlluminationMode::DDGI:
|
case GlobalIlluminationMode::DDGI:
|
||||||
@@ -865,6 +1011,8 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
|||||||
for (const auto& e : surfaceAtlasData.Objects)
|
for (const auto& e : surfaceAtlasData.Objects)
|
||||||
{
|
{
|
||||||
const auto& object = e.Value;
|
const auto& object = e.Value;
|
||||||
|
if (!allLightingDirty && object.LightingUpdateFrame != currentFrame)
|
||||||
|
continue;
|
||||||
for (int32 tileIndex = 0; tileIndex < 6; tileIndex++)
|
for (int32 tileIndex = 0; tileIndex < 6; tileIndex++)
|
||||||
{
|
{
|
||||||
auto* tile = object.Tiles[tileIndex];
|
auto* tile = object.Tiles[tileIndex];
|
||||||
@@ -873,6 +1021,9 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
|||||||
VB_WRITE_TILE(tile);
|
VB_WRITE_TILE(tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_vertexBuffer->Data.Count() == 0)
|
||||||
|
break;
|
||||||
|
PROFILE_GPU_CPU("DDGI");
|
||||||
data.DDGI = bindingDataDDGI.Constants;
|
data.DDGI = bindingDataDDGI.Constants;
|
||||||
context->BindSR(5, bindingDataDDGI.ProbesState);
|
context->BindSR(5, bindingDataDDGI.ProbesState);
|
||||||
context->BindSR(6, bindingDataDDGI.ProbesDistance);
|
context->BindSR(6, bindingDataDDGI.ProbesDistance);
|
||||||
@@ -1065,7 +1216,7 @@ void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, con
|
|||||||
|
|
||||||
// Redraw objects from time-to-time (dynamic objects can be animated, static objects can have textures streamed)
|
// Redraw objects from time-to-time (dynamic objects can be animated, static objects can have textures streamed)
|
||||||
uint32 redrawFramesCount = actor->HasStaticFlag(StaticFlags::Lightmap) ? 120 : 4;
|
uint32 redrawFramesCount = actor->HasStaticFlag(StaticFlags::Lightmap) ? 120 : 4;
|
||||||
if (surfaceAtlasData.CurrentFrame - object->LastFrameDirty >= (redrawFramesCount + (actor->GetID().D & redrawFramesCount)))
|
if (surfaceAtlasData.CurrentFrame - object->LastFrameUpdated >= (redrawFramesCount + (actor->GetID().D & redrawFramesCount)))
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
|
||||||
// Mark object as used
|
// Mark object as used
|
||||||
@@ -1076,7 +1227,8 @@ void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, con
|
|||||||
object->Radius = (float)actorObjectBounds.Radius;
|
object->Radius = (float)actorObjectBounds.Radius;
|
||||||
if (dirty || GLOBAL_SURFACE_ATLAS_DEBUG_FORCE_REDRAW_TILES)
|
if (dirty || GLOBAL_SURFACE_ATLAS_DEBUG_FORCE_REDRAW_TILES)
|
||||||
{
|
{
|
||||||
object->LastFrameDirty = surfaceAtlasData.CurrentFrame;
|
object->LastFrameUpdated = surfaceAtlasData.CurrentFrame;
|
||||||
|
object->LightingUpdateFrame = surfaceAtlasData.CurrentFrame;
|
||||||
_dirtyObjectsBuffer.Add(actorObject);
|
_dirtyObjectsBuffer.Add(actorObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ private:
|
|||||||
bool _supported = false;
|
bool _supported = false;
|
||||||
AssetReference<Shader> _shader;
|
AssetReference<Shader> _shader;
|
||||||
GPUPipelineState* _psClear = nullptr;
|
GPUPipelineState* _psClear = nullptr;
|
||||||
|
GPUPipelineState* _psClearLighting = nullptr;
|
||||||
GPUPipelineState* _psDirectLighting0 = nullptr;
|
GPUPipelineState* _psDirectLighting0 = nullptr;
|
||||||
GPUPipelineState* _psDirectLighting1 = nullptr;
|
GPUPipelineState* _psDirectLighting1 = nullptr;
|
||||||
GPUPipelineState* _psIndirectLighting = nullptr;
|
GPUPipelineState* _psIndirectLighting = nullptr;
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ struct RendererDirectionalLightData
|
|||||||
float ShadowsSharpness;
|
float ShadowsSharpness;
|
||||||
float VolumetricScatteringIntensity;
|
float VolumetricScatteringIntensity;
|
||||||
|
|
||||||
|
StaticFlags StaticFlags;
|
||||||
float IndirectLightingIntensity;
|
float IndirectLightingIntensity;
|
||||||
int8 CastVolumetricShadow : 1;
|
int8 CastVolumetricShadow : 1;
|
||||||
int8 RenderedVolumetricFog : 1;
|
int8 RenderedVolumetricFog : 1;
|
||||||
@@ -43,6 +44,8 @@ struct RendererDirectionalLightData
|
|||||||
float ContactShadowsLength;
|
float ContactShadowsLength;
|
||||||
ShadowsCastingMode ShadowsMode;
|
ShadowsCastingMode ShadowsMode;
|
||||||
|
|
||||||
|
Guid ID;
|
||||||
|
|
||||||
void SetupLightData(LightData* data, bool useShadow) const;
|
void SetupLightData(LightData* data, bool useShadow) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -76,11 +79,13 @@ struct RendererSpotLightData
|
|||||||
float IndirectLightingIntensity;
|
float IndirectLightingIntensity;
|
||||||
ShadowsCastingMode ShadowsMode;
|
ShadowsCastingMode ShadowsMode;
|
||||||
|
|
||||||
|
StaticFlags StaticFlags;
|
||||||
int8 CastVolumetricShadow : 1;
|
int8 CastVolumetricShadow : 1;
|
||||||
int8 RenderedVolumetricFog : 1;
|
int8 RenderedVolumetricFog : 1;
|
||||||
int8 UseInverseSquaredFalloff : 1;
|
int8 UseInverseSquaredFalloff : 1;
|
||||||
|
|
||||||
GPUTexture* IESTexture;
|
GPUTexture* IESTexture;
|
||||||
|
Guid ID;
|
||||||
|
|
||||||
void SetupLightData(LightData* data, bool useShadow) const;
|
void SetupLightData(LightData* data, bool useShadow) const;
|
||||||
};
|
};
|
||||||
@@ -111,11 +116,13 @@ struct RendererPointLightData
|
|||||||
float IndirectLightingIntensity;
|
float IndirectLightingIntensity;
|
||||||
ShadowsCastingMode ShadowsMode;
|
ShadowsCastingMode ShadowsMode;
|
||||||
|
|
||||||
|
StaticFlags StaticFlags;
|
||||||
int8 CastVolumetricShadow : 1;
|
int8 CastVolumetricShadow : 1;
|
||||||
int8 RenderedVolumetricFog : 1;
|
int8 RenderedVolumetricFog : 1;
|
||||||
int8 UseInverseSquaredFalloff : 1;
|
int8 UseInverseSquaredFalloff : 1;
|
||||||
|
|
||||||
GPUTexture* IESTexture;
|
GPUTexture* IESTexture;
|
||||||
|
Guid ID;
|
||||||
|
|
||||||
void SetupLightData(LightData* data, bool useShadow) const;
|
void SetupLightData(LightData* data, bool useShadow) const;
|
||||||
};
|
};
|
||||||
@@ -131,10 +138,12 @@ struct RendererSkyLightData
|
|||||||
Float3 AdditiveColor;
|
Float3 AdditiveColor;
|
||||||
float IndirectLightingIntensity;
|
float IndirectLightingIntensity;
|
||||||
|
|
||||||
|
StaticFlags StaticFlags;
|
||||||
int8 CastVolumetricShadow : 1;
|
int8 CastVolumetricShadow : 1;
|
||||||
int8 RenderedVolumetricFog : 1;
|
int8 RenderedVolumetricFog : 1;
|
||||||
|
|
||||||
CubeTexture* Image;
|
CubeTexture* Image;
|
||||||
|
Guid ID;
|
||||||
|
|
||||||
void SetupLightData(LightData* data, bool useShadow) const;
|
void SetupLightData(LightData* data, bool useShadow) const;
|
||||||
};
|
};
|
||||||
@@ -211,7 +220,6 @@ struct DrawBatch
|
|||||||
class RenderListAllocation
|
class RenderListAllocation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static FLAXENGINE_API void* Allocate(uintptr size);
|
static FLAXENGINE_API void* Allocate(uintptr size);
|
||||||
static FLAXENGINE_API void Free(void* ptr, uintptr size);
|
static FLAXENGINE_API void Free(void* ptr, uintptr size);
|
||||||
|
|
||||||
@@ -222,7 +230,6 @@ public:
|
|||||||
uintptr _size;
|
uintptr _size;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FORCE_INLINE Data()
|
FORCE_INLINE Data()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -329,7 +336,7 @@ struct DrawCallsList
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
API_CLASS(Sealed) class FLAXENGINE_API RenderList : public ScriptingObject
|
API_CLASS(Sealed) class FLAXENGINE_API RenderList : public ScriptingObject
|
||||||
{
|
{
|
||||||
DECLARE_SCRIPTING_TYPE(RenderList);
|
DECLARE_SCRIPTING_TYPE(RenderList);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allocates the new renderer list object or reuses already allocated one.
|
/// Allocates the new renderer list object or reuses already allocated one.
|
||||||
@@ -349,7 +356,6 @@ DECLARE_SCRIPTING_TYPE(RenderList);
|
|||||||
static void CleanupCache();
|
static void CleanupCache();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// All scenes for rendering.
|
/// All scenes for rendering.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -458,11 +464,9 @@ public:
|
|||||||
Float3 FrustumCornersVs[8];
|
Float3 FrustumCornersVs[8];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
DynamicVertexBuffer _instanceBuffer;
|
DynamicVertexBuffer _instanceBuffer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Blends the postprocessing settings into the final options.
|
/// Blends the postprocessing settings into the final options.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -527,7 +531,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Init cache for given task
|
/// Init cache for given task
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -540,7 +543,6 @@ public:
|
|||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the draw call to the draw lists.
|
/// Adds the draw call to the draw lists.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -62,6 +62,22 @@ void PS_Clear(out float4 Light : SV_Target0, out float4 RT0 : SV_Target1, out fl
|
|||||||
RT2 = float4(1, 0, 0, 0);
|
RT2 = float4(1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _PS_ClearLighting
|
||||||
|
|
||||||
|
Buffer<float4> GlobalSurfaceAtlasObjects : register(t4);
|
||||||
|
Texture2D Texture : register(t7);
|
||||||
|
|
||||||
|
// Pixel shader for Global Surface Atlas clearing
|
||||||
|
META_PS(true, FEATURE_LEVEL_SM5)
|
||||||
|
float4 PS_ClearLighting(AtlasVertexOutput input) : SV_Target
|
||||||
|
{
|
||||||
|
GlobalSurfaceTile tile = LoadGlobalSurfaceAtlasTile(GlobalSurfaceAtlasObjects, input.TileAddress);
|
||||||
|
float2 atlasUV = input.TileUV * tile.AtlasRectUV.zw + tile.AtlasRectUV.xy;
|
||||||
|
return Texture.Sample(SamplerPointClamp, atlasUV);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _PS_Lighting
|
#ifdef _PS_Lighting
|
||||||
|
|
||||||
#include "./Flax/GBuffer.hlsl"
|
#include "./Flax/GBuffer.hlsl"
|
||||||
@@ -79,7 +95,7 @@ Texture3D<float> GlobalSDFTex : register(t5);
|
|||||||
Texture3D<float> GlobalSDFMip : register(t6);
|
Texture3D<float> GlobalSDFMip : register(t6);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Pixel shader for Global Surface Atlas shading with direct light contribution
|
// Pixel shader for Global Surface Atlas shading
|
||||||
META_PS(true, FEATURE_LEVEL_SM5)
|
META_PS(true, FEATURE_LEVEL_SM5)
|
||||||
META_PERMUTATION_1(RADIAL_LIGHT=0)
|
META_PERMUTATION_1(RADIAL_LIGHT=0)
|
||||||
META_PERMUTATION_1(RADIAL_LIGHT=1)
|
META_PERMUTATION_1(RADIAL_LIGHT=1)
|
||||||
|
|||||||
Reference in New Issue
Block a user