Merge branch 'FlaxEngine:master' into master
This commit is contained in:
@@ -187,7 +187,7 @@ BoundingBox Model::GetBox(int32 lodIndex) const
|
||||
return LODs[lodIndex].GetBox();
|
||||
}
|
||||
|
||||
void Model::Draw(const RenderContext& renderContext, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals) const
|
||||
void Model::Draw(const RenderContext& renderContext, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals, int16 sortOrder) const
|
||||
{
|
||||
if (!CanBeRendered())
|
||||
return;
|
||||
@@ -203,7 +203,7 @@ void Model::Draw(const RenderContext& renderContext, MaterialBase* material, con
|
||||
lodIndex = ClampLODIndex(lodIndex);
|
||||
|
||||
// Draw
|
||||
LODs[lodIndex].Draw(renderContext, material, world, flags, receiveDecals);
|
||||
LODs[lodIndex].Draw(renderContext, material, world, flags, receiveDecals, DrawPass::Default, 0, sortOrder);
|
||||
}
|
||||
|
||||
template<typename ContextType>
|
||||
|
||||
@@ -181,7 +181,8 @@ public:
|
||||
/// <param name="world">The world transformation of the model.</param>
|
||||
/// <param name="flags">The object static flags.</param>
|
||||
/// <param name="receiveDecals">True if rendered geometry can receive decals, otherwise false.</param>
|
||||
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true) const;
|
||||
/// <param name="sortOrder">Object sorting key.</param>
|
||||
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, int16 sortOrder = 0) const;
|
||||
|
||||
/// <summary>
|
||||
/// Draws the model.
|
||||
|
||||
@@ -161,6 +161,11 @@ namespace FlaxEngine
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the aspect ratio used by the viewport.
|
||||
/// </summary>
|
||||
public float AspectRatio => !Mathf.IsZero(Height) ? Width / Height : 0f;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified <see cref="Viewport"/> is equal to this instance.
|
||||
/// </summary>
|
||||
@@ -326,21 +331,5 @@ namespace FlaxEngine
|
||||
vector /= w;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the aspect ratio used by the viewport.
|
||||
/// </summary>
|
||||
/// <value>The aspect ratio.</value>
|
||||
public float AspectRatio
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Mathf.IsZero(Height))
|
||||
{
|
||||
return Width / Height;
|
||||
}
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,5 +164,12 @@ constexpr bool EnumHasAllFlags(T value, T flags)
|
||||
return ((__underlying_type(T))value & (__underlying_type(T))flags) == (__underlying_type(T))flags;
|
||||
}
|
||||
|
||||
// Returns true if given enum value has none of enum flags set
|
||||
template<typename T>
|
||||
constexpr bool EnumHasNoneFlags(T value, T flags)
|
||||
{
|
||||
return ((__underlying_type(T))value & (__underlying_type(T))flags) == 0;
|
||||
}
|
||||
|
||||
// Returns byte offset from the object pointer in vtable to the begin of the given inherited type implementation
|
||||
#define VTABLE_OFFSET(type, baseType) (((intptr)static_cast<baseType*>((type*)1))-1)
|
||||
|
||||
@@ -140,13 +140,13 @@ struct PsData
|
||||
|
||||
bool Create(GPUPipelineState::Description& desc)
|
||||
{
|
||||
desc.DepthTestEnable = true;
|
||||
desc.DepthEnable = true;
|
||||
desc.DepthWriteEnable = false;
|
||||
|
||||
Depth = GPUDevice::Instance->CreatePipelineState();
|
||||
if (Depth->Init(desc))
|
||||
return true;
|
||||
desc.DepthTestEnable = false;
|
||||
desc.DepthEnable = false;
|
||||
NoDepthTest = GPUDevice::Instance->CreatePipelineState();
|
||||
if (NoDepthTest->Init(desc))
|
||||
return false;
|
||||
@@ -156,7 +156,7 @@ struct PsData
|
||||
NoDepthTestDepthWrite = GPUDevice::Instance->CreatePipelineState();
|
||||
if (NoDepthTestDepthWrite->Init(desc))
|
||||
return false;
|
||||
desc.DepthTestEnable = true;
|
||||
desc.DepthEnable = true;
|
||||
DepthWrite = GPUDevice::Instance->CreatePipelineState();
|
||||
return DepthWrite->Init(desc);
|
||||
}
|
||||
|
||||
@@ -514,7 +514,7 @@ public:
|
||||
API_FIELD(ReadOnly) static BlendingMode Additive;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the alpha blending.
|
||||
/// Gets the alpha blending. Source alpha controls the output color (0 - use destination color, 1 - use source color).
|
||||
/// </summary>
|
||||
API_FIELD(ReadOnly) static BlendingMode AlphaBlend;
|
||||
|
||||
@@ -591,22 +591,22 @@ API_ENUM() enum class Quality : byte
|
||||
API_ENUM() enum class MaterialPostFxLocation : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// The after post processing pass using LDR input frame.
|
||||
/// The 'after' post processing pass using LDR input frame.
|
||||
/// </summary>
|
||||
AfterPostProcessingPass = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The before post processing pass using HDR input frame.
|
||||
/// The 'before' post processing pass using HDR input frame.
|
||||
/// </summary>
|
||||
BeforePostProcessingPass = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The before forward pass but after GBuffer with HDR input frame.
|
||||
/// The 'before' forward pass but after GBuffer with HDR input frame.
|
||||
/// </summary>
|
||||
BeforeForwardPass = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The after custom post effects.
|
||||
/// The 'after' custom post effects.
|
||||
/// </summary>
|
||||
AfterCustomPostEffects = 3,
|
||||
|
||||
@@ -620,6 +620,11 @@ API_ENUM() enum class MaterialPostFxLocation : byte
|
||||
/// </summary>
|
||||
AfterAntiAliasingPass = 5,
|
||||
|
||||
/// <summary>
|
||||
/// The 'after' forward pass but before any post processing.
|
||||
/// </summary>
|
||||
AfterForwardPass = 6,
|
||||
|
||||
API_ENUM(Attributes="HideInEditor")
|
||||
MAX,
|
||||
};
|
||||
@@ -635,7 +640,7 @@ API_ENUM() enum class PostProcessEffectLocation
|
||||
Default = 0,
|
||||
|
||||
/// <summary>
|
||||
///The 'before' in-build PostFx pass (bloom, color grading, etc.). After Forward Pass (transparency) and fog effects.
|
||||
/// The 'before' in-build PostFx pass (bloom, color grading, etc.). After Forward Pass (transparency) and fog effects.
|
||||
/// </summary>
|
||||
BeforePostProcessingPass = 1,
|
||||
|
||||
@@ -659,6 +664,16 @@ API_ENUM() enum class PostProcessEffectLocation
|
||||
/// </summary>
|
||||
CustomUpscale = 5,
|
||||
|
||||
/// <summary>
|
||||
/// The 'after' GBuffer rendering pass. Can be used to render custom geometry into GBuffer. Output is light buffer, single-target only (no output).
|
||||
/// </summary>
|
||||
AfterGBufferPass = 6,
|
||||
|
||||
/// <summary>
|
||||
/// The 'after' forward pass but before any post processing.
|
||||
/// </summary>
|
||||
AfterForwardPass = 7,
|
||||
|
||||
API_ENUM(Attributes="HideInEditor")
|
||||
MAX,
|
||||
};
|
||||
@@ -874,7 +889,7 @@ API_ENUM() enum class ViewMode
|
||||
/// <summary>
|
||||
/// Frame rendering flags used to switch between graphics features.
|
||||
/// </summary>
|
||||
API_ENUM(Attributes="Flags") enum class ViewFlags : int64
|
||||
API_ENUM(Attributes="Flags") enum class ViewFlags : uint64
|
||||
{
|
||||
/// <summary>
|
||||
/// Nothing.
|
||||
@@ -1011,20 +1026,25 @@ API_ENUM(Attributes="Flags") enum class ViewFlags : int64
|
||||
/// </summary>
|
||||
GlobalSDF = 1 << 25,
|
||||
|
||||
/// <summary>
|
||||
/// Shows/hides the Sky/Skybox rendering.
|
||||
/// </summary>
|
||||
Sky = 1 << 26,
|
||||
|
||||
/// <summary>
|
||||
/// Default flags for Game.
|
||||
/// </summary>
|
||||
DefaultGame = Reflections | DepthOfField | Fog | Decals | MotionBlur | SSR | AO | GI | DirectionalLights | PointLights | SpotLights | SkyLights | Shadows | SpecularLight | AntiAliasing | CustomPostProcess | Bloom | ToneMapping | EyeAdaptation | CameraArtifacts | LensFlares | ContactShadows | GlobalSDF,
|
||||
DefaultGame = Reflections | DepthOfField | Fog | Decals | MotionBlur | SSR | AO | GI | DirectionalLights | PointLights | SpotLights | SkyLights | Shadows | SpecularLight | AntiAliasing | CustomPostProcess | Bloom | ToneMapping | EyeAdaptation | CameraArtifacts | LensFlares | ContactShadows | GlobalSDF | Sky,
|
||||
|
||||
/// <summary>
|
||||
/// Default flags for Editor.
|
||||
/// </summary>
|
||||
DefaultEditor = Reflections | Fog | Decals | DebugDraw | SSR | AO | GI | DirectionalLights | PointLights | SpotLights | SkyLights | Shadows | SpecularLight | AntiAliasing | CustomPostProcess | Bloom | ToneMapping | EyeAdaptation | CameraArtifacts | LensFlares | EditorSprites | ContactShadows | GlobalSDF,
|
||||
DefaultEditor = Reflections | Fog | Decals | DebugDraw | SSR | AO | GI | DirectionalLights | PointLights | SpotLights | SkyLights | Shadows | SpecularLight | AntiAliasing | CustomPostProcess | Bloom | ToneMapping | EyeAdaptation | CameraArtifacts | LensFlares | EditorSprites | ContactShadows | GlobalSDF | Sky,
|
||||
|
||||
/// <summary>
|
||||
/// Default flags for materials/models previews generating.
|
||||
/// </summary>
|
||||
DefaultAssetPreview = Reflections | Decals | DirectionalLights | PointLights | SpotLights | SkyLights | SpecularLight | AntiAliasing | Bloom | ToneMapping | EyeAdaptation | CameraArtifacts | LensFlares | ContactShadows,
|
||||
DefaultAssetPreview = Reflections | Decals | DirectionalLights | PointLights | SpotLights | SkyLights | SpecularLight | AntiAliasing | Bloom | ToneMapping | EyeAdaptation | CameraArtifacts | LensFlares | ContactShadows | Sky,
|
||||
};
|
||||
|
||||
DECLARE_ENUM_OPERATORS(ViewFlags);
|
||||
|
||||
@@ -315,6 +315,12 @@ public:
|
||||
/// <param name="rts">The array with render targets to bind.</param>
|
||||
API_FUNCTION() virtual void SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPUTextureView*>& rts) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the blend factor that modulate values for a pixel shader, render target, or both.
|
||||
/// </summary>
|
||||
/// <param name="value">Blend factors, one for each RGBA component.</param>
|
||||
API_FUNCTION() virtual void SetBlendFactor(const Float4& value) = 0;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Unbinds all shader resource slots and flushes the change with the driver (used to prevent driver detection of resource hazards, eg. when down-scaling the texture).
|
||||
|
||||
@@ -76,7 +76,7 @@ bool GPUPipelineState::Init(const Description& desc)
|
||||
Complexity += tessCost;
|
||||
if (desc.DepthWriteEnable)
|
||||
Complexity += 5;
|
||||
if (desc.DepthTestEnable)
|
||||
if (desc.DepthEnable)
|
||||
Complexity += 5;
|
||||
if (desc.BlendMode.BlendEnable)
|
||||
Complexity += 20;
|
||||
|
||||
@@ -134,7 +134,7 @@ public:
|
||||
/// <summary>
|
||||
/// Quad rendering shader
|
||||
/// </summary>
|
||||
GPUShader* QuadShader;
|
||||
API_FIELD(ReadOnly) GPUShader* QuadShader;
|
||||
|
||||
/// <summary>
|
||||
/// The current task being executed.
|
||||
|
||||
@@ -24,16 +24,16 @@ public:
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_NO_SPAWN(Description);
|
||||
|
||||
/// <summary>
|
||||
/// Enable/disable depth (DepthFunc and DepthWriteEnable)
|
||||
/// </summary>
|
||||
API_FIELD() bool DepthEnable;
|
||||
|
||||
/// <summary>
|
||||
/// Enable/disable depth write
|
||||
/// </summary>
|
||||
API_FIELD() bool DepthWriteEnable;
|
||||
|
||||
/// <summary>
|
||||
/// Enable/disable depth test
|
||||
/// </summary>
|
||||
API_FIELD() bool DepthTestEnable;
|
||||
|
||||
/// <summary>
|
||||
/// Enable/disable depth clipping
|
||||
/// </summary>
|
||||
|
||||
@@ -137,8 +137,13 @@ void DeferredMaterialShader::Unload()
|
||||
bool DeferredMaterialShader::Load()
|
||||
{
|
||||
auto psDesc = GPUPipelineState::Description::Default;
|
||||
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
|
||||
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
|
||||
if (EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthTest))
|
||||
{
|
||||
psDesc.DepthFunc = ComparisonFunc::Always;
|
||||
if (!psDesc.DepthWriteEnable)
|
||||
psDesc.DepthEnable = false;
|
||||
}
|
||||
|
||||
// Check if use tessellation (both material and runtime supports it)
|
||||
const bool useTess = _info.TessellationMode != TessellationMethod::None && GPUDevice::Instance->Limits.HasTessellation;
|
||||
@@ -183,7 +188,7 @@ bool DeferredMaterialShader::Load()
|
||||
|
||||
// Motion Vectors pass
|
||||
psDesc.DepthWriteEnable = false;
|
||||
psDesc.DepthTestEnable = true;
|
||||
psDesc.DepthEnable = true;
|
||||
psDesc.DepthFunc = ComparisonFunc::LessEqual;
|
||||
psDesc.VS = _shader->GetVS("VS");
|
||||
psDesc.PS = _shader->GetPS("PS_MotionVectors");
|
||||
@@ -201,7 +206,7 @@ bool DeferredMaterialShader::Load()
|
||||
psDesc.CullMode = CullMode::TwoSided;
|
||||
psDesc.DepthClipEnable = false;
|
||||
psDesc.DepthWriteEnable = true;
|
||||
psDesc.DepthTestEnable = true;
|
||||
psDesc.DepthEnable = true;
|
||||
psDesc.DepthFunc = ComparisonFunc::Less;
|
||||
psDesc.HS = nullptr;
|
||||
psDesc.DS = nullptr;
|
||||
|
||||
@@ -112,7 +112,7 @@ bool DeformableMaterialShader::Load()
|
||||
{
|
||||
_drawModes = DrawPass::Depth | DrawPass::QuadOverdraw;
|
||||
auto psDesc = GPUPipelineState::Description::Default;
|
||||
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
|
||||
psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
|
||||
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
|
||||
|
||||
// Check if use tessellation (both material and runtime supports it)
|
||||
@@ -170,7 +170,7 @@ bool DeformableMaterialShader::Load()
|
||||
psDesc.CullMode = CullMode::TwoSided;
|
||||
psDesc.DepthClipEnable = false;
|
||||
psDesc.DepthWriteEnable = true;
|
||||
psDesc.DepthTestEnable = true;
|
||||
psDesc.DepthEnable = true;
|
||||
psDesc.DepthFunc = ComparisonFunc::Less;
|
||||
psDesc.HS = nullptr;
|
||||
psDesc.DS = nullptr;
|
||||
|
||||
@@ -130,7 +130,7 @@ bool ForwardMaterialShader::Load()
|
||||
_drawModes = DrawPass::Depth | DrawPass::Forward | DrawPass::QuadOverdraw;
|
||||
|
||||
auto psDesc = GPUPipelineState::Description::Default;
|
||||
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
|
||||
psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
|
||||
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
|
||||
|
||||
// Check if use tessellation (both material and runtime supports it)
|
||||
@@ -200,7 +200,7 @@ bool ForwardMaterialShader::Load()
|
||||
psDesc.CullMode = CullMode::TwoSided;
|
||||
psDesc.DepthClipEnable = false;
|
||||
psDesc.DepthWriteEnable = true;
|
||||
psDesc.DepthTestEnable = true;
|
||||
psDesc.DepthEnable = true;
|
||||
psDesc.DepthFunc = ComparisonFunc::Less;
|
||||
psDesc.HS = nullptr;
|
||||
psDesc.DS = nullptr;
|
||||
|
||||
@@ -89,13 +89,13 @@ bool GUIMaterialShader::Load()
|
||||
psDesc0.PS = _shader->GetPS("PS_GUI");
|
||||
psDesc0.BlendMode = BlendingMode::AlphaBlend;
|
||||
|
||||
psDesc0.DepthTestEnable = psDesc0.DepthWriteEnable = true;
|
||||
psDesc0.DepthEnable = psDesc0.DepthWriteEnable = true;
|
||||
_cache.Depth = GPUDevice::Instance->CreatePipelineState();
|
||||
_cache.NoDepth = GPUDevice::Instance->CreatePipelineState();
|
||||
|
||||
bool failed = _cache.Depth->Init(psDesc0);
|
||||
|
||||
psDesc0.DepthTestEnable = psDesc0.DepthWriteEnable = false;
|
||||
psDesc0.DepthEnable = psDesc0.DepthWriteEnable = false;
|
||||
failed |= _cache.NoDepth->Init(psDesc0);
|
||||
|
||||
if (failed)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/// <summary>
|
||||
/// Current materials shader version.
|
||||
/// </summary>
|
||||
#define MATERIAL_GRAPH_VERSION 159
|
||||
#define MATERIAL_GRAPH_VERSION 161
|
||||
|
||||
class Material;
|
||||
class GPUShader;
|
||||
|
||||
@@ -154,9 +154,6 @@ void ParticleMaterialShader::Bind(BindParameters& params)
|
||||
materialData->RibbonUVOffset.Y = drawCall.Particle.Ribbon.UVOffsetY;
|
||||
materialData->RibbonSegmentCount = drawCall.Particle.Ribbon.SegmentCount;
|
||||
|
||||
if (drawCall.Particle.Ribbon.SegmentDistances)
|
||||
context->BindSR(1, drawCall.Particle.Ribbon.SegmentDistances->View());
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -189,7 +186,7 @@ bool ParticleMaterialShader::Load()
|
||||
{
|
||||
_drawModes = DrawPass::Depth | DrawPass::Forward | DrawPass::QuadOverdraw;
|
||||
GPUPipelineState::Description psDesc = GPUPipelineState::Description::Default;
|
||||
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
|
||||
psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
|
||||
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
|
||||
|
||||
auto vsSprite = _shader->GetVS("VS_Sprite");
|
||||
|
||||
@@ -133,7 +133,7 @@ void TerrainMaterialShader::Unload()
|
||||
bool TerrainMaterialShader::Load()
|
||||
{
|
||||
GPUPipelineState::Description psDesc = GPUPipelineState::Description::Default;
|
||||
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
|
||||
psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
|
||||
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
|
||||
|
||||
// Check if use tessellation (both material and runtime supports it)
|
||||
@@ -182,7 +182,7 @@ bool TerrainMaterialShader::Load()
|
||||
psDesc.BlendMode = BlendingMode::Opaque;
|
||||
psDesc.DepthClipEnable = false;
|
||||
psDesc.DepthWriteEnable = true;
|
||||
psDesc.DepthTestEnable = true;
|
||||
psDesc.DepthEnable = true;
|
||||
psDesc.DepthFunc = ComparisonFunc::Less;
|
||||
psDesc.HS = nullptr;
|
||||
psDesc.DS = nullptr;
|
||||
|
||||
@@ -6,14 +6,11 @@
|
||||
#include "ModelInstanceEntry.h"
|
||||
#include "Config.h"
|
||||
#include "Types.h"
|
||||
#include "Engine/Level/Types.h"
|
||||
#if USE_PRECISE_MESH_INTERSECTS
|
||||
#include "CollisionProxy.h"
|
||||
#endif
|
||||
|
||||
struct GeometryDrawStateData;
|
||||
class Lightmap;
|
||||
class GPUBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Represents part of the model that is made of vertices and can be rendered using custom material and transformation.
|
||||
@@ -275,77 +272,6 @@ public:
|
||||
/// <param name="drawCall">The draw call.</param>
|
||||
void GetDrawCallGeometry(DrawCall& drawCall) const;
|
||||
|
||||
/// <summary>
|
||||
/// Model instance drawing packed data.
|
||||
/// </summary>
|
||||
struct DrawInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The instance buffer to use during model rendering.
|
||||
/// </summary>
|
||||
ModelInstanceEntries* Buffer;
|
||||
|
||||
/// <summary>
|
||||
/// The world transformation of the model.
|
||||
/// </summary>
|
||||
Matrix* World;
|
||||
|
||||
/// <summary>
|
||||
/// The instance drawing state data container. Used for LOD transition handling and previous world transformation matrix updating.
|
||||
/// </summary>
|
||||
GeometryDrawStateData* DrawState;
|
||||
|
||||
/// <summary>
|
||||
/// The lightmap.
|
||||
/// </summary>
|
||||
const Lightmap* Lightmap;
|
||||
|
||||
/// <summary>
|
||||
/// The lightmap UVs.
|
||||
/// </summary>
|
||||
const Rectangle* LightmapUVs;
|
||||
|
||||
/// <summary>
|
||||
/// The model instance vertex colors buffers (per-lod all meshes packed in a single allocation, array length equal to model lods count).
|
||||
/// </summary>
|
||||
GPUBuffer** VertexColors;
|
||||
|
||||
/// <summary>
|
||||
/// The object static flags.
|
||||
/// </summary>
|
||||
StaticFlags Flags;
|
||||
|
||||
/// <summary>
|
||||
/// The object draw modes.
|
||||
/// </summary>
|
||||
DrawPass DrawModes;
|
||||
|
||||
/// <summary>
|
||||
/// The bounds of the model (used to select a proper LOD during rendering).
|
||||
/// </summary>
|
||||
BoundingSphere Bounds;
|
||||
|
||||
/// <summary>
|
||||
/// The per-instance random value.
|
||||
/// </summary>
|
||||
float PerInstanceRandom;
|
||||
|
||||
/// <summary>
|
||||
/// The LOD bias value.
|
||||
/// </summary>
|
||||
char LODBias;
|
||||
|
||||
/// <summary>
|
||||
/// The forced LOD to use. Value -1 disables this feature.
|
||||
/// </summary>
|
||||
char ForcedLOD;
|
||||
|
||||
/// <summary>
|
||||
/// The object sorting key.
|
||||
/// </summary>
|
||||
int16 SortOrder;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Draws the mesh. Binds vertex and index buffers and invokes the draw call.
|
||||
/// </summary>
|
||||
|
||||
@@ -5,12 +5,20 @@
|
||||
#include "Engine/Core/Math/BoundingBox.h"
|
||||
#include "Engine/Core/Math/BoundingSphere.h"
|
||||
#include "Engine/Core/Types/DataContainer.h"
|
||||
#include "Engine/Graphics/Enums.h"
|
||||
#include "Engine/Graphics/Models/Types.h"
|
||||
#include "Engine/Level/Types.h"
|
||||
#include "Engine/Scripting/ScriptingObject.h"
|
||||
|
||||
struct GeometryDrawStateData;
|
||||
struct RenderContext;
|
||||
struct RenderContextBatch;
|
||||
class Task;
|
||||
class ModelBase;
|
||||
struct RenderContextBatch;
|
||||
class Lightmap;
|
||||
class GPUBuffer;
|
||||
class SkinnedMeshDrawData;
|
||||
class BlendShapesInstance;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for model resources meshes.
|
||||
@@ -143,4 +151,95 @@ public:
|
||||
/// <param name="count">The amount of items inside the result buffer.</param>
|
||||
/// <returns>True if failed, otherwise false</returns>
|
||||
virtual bool DownloadDataCPU(MeshBufferType type, BytesContainer& result, int32& count) const = 0;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Model instance drawing packed data.
|
||||
/// </summary>
|
||||
struct DrawInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The instance buffer to use during model rendering
|
||||
/// </summary>
|
||||
ModelInstanceEntries* Buffer;
|
||||
|
||||
/// <summary>
|
||||
/// The world transformation of the model.
|
||||
/// </summary>
|
||||
Matrix* World;
|
||||
|
||||
/// <summary>
|
||||
/// The instance drawing state data container. Used for LOD transition handling and previous world transformation matrix updating.
|
||||
/// </summary>
|
||||
GeometryDrawStateData* DrawState;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
/// <summary>
|
||||
/// The skinning.
|
||||
/// </summary>
|
||||
SkinnedMeshDrawData* Skinning;
|
||||
|
||||
/// <summary>
|
||||
/// The blend shapes.
|
||||
/// </summary>
|
||||
BlendShapesInstance* BlendShapes;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
/// <summary>
|
||||
/// The lightmap.
|
||||
/// </summary>
|
||||
const Lightmap* Lightmap;
|
||||
|
||||
/// <summary>
|
||||
/// The lightmap UVs.
|
||||
/// </summary>
|
||||
const Rectangle* LightmapUVs;
|
||||
};
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The model instance vertex colors buffers (per-lod all meshes packed in a single allocation, array length equal to model lods count).
|
||||
/// </summary>
|
||||
GPUBuffer** VertexColors;
|
||||
|
||||
/// <summary>
|
||||
/// The object static flags.
|
||||
/// </summary>
|
||||
StaticFlags Flags;
|
||||
|
||||
/// <summary>
|
||||
/// The object draw modes.
|
||||
/// </summary>
|
||||
DrawPass DrawModes;
|
||||
|
||||
/// <summary>
|
||||
/// The bounds of the model (used to select a proper LOD during rendering).
|
||||
/// </summary>
|
||||
BoundingSphere Bounds;
|
||||
|
||||
/// <summary>
|
||||
/// The per-instance random value.
|
||||
/// </summary>
|
||||
float PerInstanceRandom;
|
||||
|
||||
/// <summary>
|
||||
/// The LOD bias value.
|
||||
/// </summary>
|
||||
char LODBias;
|
||||
|
||||
/// <summary>
|
||||
/// The forced LOD to use. Value -1 disables this feature.
|
||||
/// </summary>
|
||||
char ForcedLOD;
|
||||
|
||||
/// <summary>
|
||||
/// The object sorting key.
|
||||
/// </summary>
|
||||
int16 SortOrder;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -119,28 +119,22 @@ bool SkinnedMesh::UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0Skinne
|
||||
bool SkinnedMesh::Intersects(const Ray& ray, const Matrix& world, Real& distance, Vector3& normal) const
|
||||
{
|
||||
// Transform points
|
||||
Vector3 min, max;
|
||||
Vector3::Transform(_box.Minimum, world, min);
|
||||
Vector3::Transform(_box.Maximum, world, max);
|
||||
BoundingBox transformedBox;
|
||||
Vector3::Transform(_box.Minimum, world, transformedBox.Minimum);
|
||||
Vector3::Transform(_box.Maximum, world, transformedBox.Maximum);
|
||||
|
||||
// Get transformed box
|
||||
BoundingBox transformedBox(min, max);
|
||||
|
||||
// Test ray on a box
|
||||
// Test ray on a transformed box
|
||||
return transformedBox.Intersects(ray, distance, normal);
|
||||
}
|
||||
|
||||
bool SkinnedMesh::Intersects(const Ray& ray, const Transform& transform, Real& distance, Vector3& normal) const
|
||||
{
|
||||
// Transform points
|
||||
Vector3 min, max;
|
||||
transform.LocalToWorld(_box.Minimum, min);
|
||||
transform.LocalToWorld(_box.Maximum, max);
|
||||
BoundingBox transformedBox;
|
||||
transform.LocalToWorld(_box.Minimum, transformedBox.Minimum);
|
||||
transform.LocalToWorld(_box.Maximum, transformedBox.Maximum);
|
||||
|
||||
// Get transformed box
|
||||
BoundingBox transformedBox(min, max);
|
||||
|
||||
// Test ray on a box
|
||||
// Test ray on a transformed box
|
||||
return transformedBox.Intersects(ray, distance, normal);
|
||||
}
|
||||
|
||||
@@ -216,7 +210,7 @@ void SkinnedMesh::Draw(const RenderContext& renderContext, const DrawInfo& info,
|
||||
drawCall.PerInstanceRandom = info.PerInstanceRandom;
|
||||
|
||||
// Push draw call to the render list
|
||||
renderContext.List->AddDrawCall(renderContext, drawModes, StaticFlags::None, drawCall, entry.ReceiveDecals);
|
||||
renderContext.List->AddDrawCall(renderContext, drawModes, StaticFlags::None, drawCall, entry.ReceiveDecals, info.SortOrder);
|
||||
}
|
||||
|
||||
void SkinnedMesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& info, float lodDitherFactor) const
|
||||
@@ -279,7 +273,7 @@ void SkinnedMesh::Draw(const RenderContextBatch& renderContextBatch, const DrawI
|
||||
const auto shadowsMode = entry.ShadowsMode & slot.ShadowsMode;
|
||||
const auto drawModes = info.DrawModes & material->GetDrawModes();
|
||||
if (drawModes != DrawPass::None)
|
||||
renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, drawModes, StaticFlags::None, shadowsMode, info.Bounds, drawCall, entry.ReceiveDecals);
|
||||
renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, drawModes, StaticFlags::None, shadowsMode, info.Bounds, drawCall, entry.ReceiveDecals, info.SortOrder);
|
||||
}
|
||||
|
||||
bool SkinnedMesh::DownloadDataGPU(MeshBufferType type, BytesContainer& result) const
|
||||
|
||||
@@ -6,11 +6,6 @@
|
||||
#include "Types.h"
|
||||
#include "BlendShape.h"
|
||||
|
||||
struct GeometryDrawStateData;
|
||||
struct RenderContext;
|
||||
class GPUBuffer;
|
||||
class SkinnedMeshDrawData;
|
||||
|
||||
/// <summary>
|
||||
/// Represents part of the skinned model that is made of vertices and can be rendered using custom material, transformation and skeleton bones hierarchy.
|
||||
/// </summary>
|
||||
@@ -170,62 +165,6 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Model instance drawing packed data.
|
||||
/// </summary>
|
||||
struct DrawInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The instance buffer to use during model rendering
|
||||
/// </summary>
|
||||
ModelInstanceEntries* Buffer;
|
||||
|
||||
/// <summary>
|
||||
/// The skinning.
|
||||
/// </summary>
|
||||
SkinnedMeshDrawData* Skinning;
|
||||
|
||||
/// <summary>
|
||||
/// The blend shapes.
|
||||
/// </summary>
|
||||
BlendShapesInstance* BlendShapes;
|
||||
|
||||
/// <summary>
|
||||
/// The world transformation of the model.
|
||||
/// </summary>
|
||||
Matrix* World;
|
||||
|
||||
/// <summary>
|
||||
/// The instance drawing state data container. Used for LOD transition handling and previous world transformation matrix updating.
|
||||
/// </summary>
|
||||
GeometryDrawStateData* DrawState;
|
||||
|
||||
/// <summary>
|
||||
/// The object draw modes.
|
||||
/// </summary>
|
||||
DrawPass DrawModes;
|
||||
|
||||
/// <summary>
|
||||
/// The bounds of the model (used to select a proper LOD during rendering).
|
||||
/// </summary>
|
||||
BoundingSphere Bounds;
|
||||
|
||||
/// <summary>
|
||||
/// The per-instance random value.
|
||||
/// </summary>
|
||||
float PerInstanceRandom;
|
||||
|
||||
/// <summary>
|
||||
/// The LOD bias value.
|
||||
/// </summary>
|
||||
char LODBias;
|
||||
|
||||
/// <summary>
|
||||
/// The forced LOD to use. Value -1 disables this feature.
|
||||
/// </summary>
|
||||
char ForcedLOD;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Draws the mesh. Binds vertex and index buffers and invokes the draw call.
|
||||
/// </summary>
|
||||
|
||||
@@ -128,6 +128,8 @@ void RenderBuffers::SetUseAlpha(bool value)
|
||||
|
||||
const RenderBuffers::CustomBuffer* RenderBuffers::FindCustomBuffer(const StringView& name) const
|
||||
{
|
||||
if (LinkedCustomBuffers)
|
||||
return LinkedCustomBuffers->FindCustomBuffer(name);
|
||||
for (const CustomBuffer* e : CustomBuffers)
|
||||
{
|
||||
if (e->Name == name)
|
||||
@@ -196,6 +198,7 @@ bool RenderBuffers::Init(int32 width, int32 height)
|
||||
void RenderBuffers::Release()
|
||||
{
|
||||
LastEyeAdaptationTime = 0;
|
||||
LinkedCustomBuffers = nullptr;
|
||||
|
||||
for (int32 i = 0; i < _resources.Count(); i++)
|
||||
_resources[i]->ReleaseGPU();
|
||||
|
||||
@@ -45,10 +45,14 @@ public:
|
||||
{
|
||||
struct
|
||||
{
|
||||
GPUTexture* GBuffer0;
|
||||
GPUTexture* GBuffer1;
|
||||
GPUTexture* GBuffer2;
|
||||
GPUTexture* GBuffer3;
|
||||
/// <summary>Gets the GBuffer texture 0. RGB: Color, A: AO</summary>
|
||||
API_FIELD(ReadOnly) GPUTexture* GBuffer0;
|
||||
/// <summary>Gets the GBuffer texture 1. RGB: Normal, A: ShadingModel</summary>
|
||||
API_FIELD(ReadOnly) GPUTexture* GBuffer1;
|
||||
/// <summary>Gets the GBuffer texture 2. R: Roughness, G: Metalness, B:Specular</summary>
|
||||
API_FIELD(ReadOnly) GPUTexture* GBuffer2;
|
||||
/// <summary>Gets the GBuffer texture 3. RGBA: Custom Data</summary>
|
||||
API_FIELD(ReadOnly) GPUTexture* GBuffer3;
|
||||
};
|
||||
|
||||
GPUTexture* GBuffer[4];
|
||||
@@ -174,6 +178,8 @@ public:
|
||||
template<class T>
|
||||
T* GetCustomBuffer(const StringView& name)
|
||||
{
|
||||
if (LinkedCustomBuffers)
|
||||
return LinkedCustomBuffers->GetCustomBuffer<T>(name);
|
||||
CustomBuffer* result = (CustomBuffer*)FindCustomBuffer(name);
|
||||
if (!result)
|
||||
{
|
||||
@@ -202,6 +208,11 @@ public:
|
||||
/// </remarks>
|
||||
API_FIELD(ReadOnly) GPUTexture* MotionVectors;
|
||||
|
||||
/// <summary>
|
||||
/// External Render Buffers used to redirect FindCustomBuffer/GetCustomBuffer calls. Can be linked to other rendering task (eg. main game viewport) to reuse graphics effect state from it (eg. use GI from main game view in in-game camera renderer).
|
||||
/// </summary>
|
||||
API_FIELD() RenderBuffers* LinkedCustomBuffers = nullptr;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Allocates the buffers.
|
||||
|
||||
@@ -181,116 +181,75 @@ uint32 GetHash(const BlendingMode& key)
|
||||
return hash;
|
||||
}
|
||||
|
||||
// @formatter:off
|
||||
|
||||
BlendingMode BlendingMode::Opaque =
|
||||
{
|
||||
false,
|
||||
// AlphaToCoverageEnable
|
||||
false,
|
||||
// BlendEnable
|
||||
Blend::One,
|
||||
// SrcBlend
|
||||
Blend::Zero,
|
||||
// DestBlend
|
||||
Operation::Add,
|
||||
// BlendOp
|
||||
Blend::One,
|
||||
// SrcBlendAlpha
|
||||
Blend::Zero,
|
||||
// DestBlendAlpha
|
||||
Operation::Add,
|
||||
// BlendOpAlpha
|
||||
ColorWrite::All,
|
||||
// RenderTargetWriteMask
|
||||
false, // AlphaToCoverageEnable
|
||||
false, // BlendEnable
|
||||
Blend::One, // SrcBlend
|
||||
Blend::Zero, // DestBlend
|
||||
Operation::Add, // BlendOp
|
||||
Blend::One, // SrcBlendAlpha
|
||||
Blend::Zero, // DestBlendAlpha
|
||||
Operation::Add, // BlendOpAlpha
|
||||
ColorWrite::All, // RenderTargetWriteMask
|
||||
};
|
||||
|
||||
BlendingMode BlendingMode::Additive =
|
||||
{
|
||||
false,
|
||||
// AlphaToCoverageEnable
|
||||
true,
|
||||
// BlendEnable
|
||||
Blend::SrcAlpha,
|
||||
// SrcBlend
|
||||
Blend::One,
|
||||
// DestBlend
|
||||
Operation::Add,
|
||||
// BlendOp
|
||||
Blend::SrcAlpha,
|
||||
// SrcBlendAlpha
|
||||
Blend::One,
|
||||
// DestBlendAlpha
|
||||
Operation::Add,
|
||||
// BlendOpAlpha
|
||||
ColorWrite::All,
|
||||
// RenderTargetWriteMask
|
||||
false, // AlphaToCoverageEnable
|
||||
true, // BlendEnable
|
||||
Blend::SrcAlpha, // SrcBlend
|
||||
Blend::One, // DestBlend
|
||||
Operation::Add, // BlendOp
|
||||
Blend::SrcAlpha, // SrcBlendAlpha
|
||||
Blend::One, // DestBlendAlpha
|
||||
Operation::Add, // BlendOpAlpha
|
||||
ColorWrite::All, // RenderTargetWriteMask
|
||||
};
|
||||
|
||||
BlendingMode BlendingMode::AlphaBlend =
|
||||
{
|
||||
false,
|
||||
// AlphaToCoverageEnable
|
||||
true,
|
||||
// BlendEnable
|
||||
Blend::SrcAlpha,
|
||||
// SrcBlend
|
||||
Blend::InvSrcAlpha,
|
||||
// DestBlend
|
||||
Operation::Add,
|
||||
// BlendOp
|
||||
Blend::One,
|
||||
// SrcBlendAlpha
|
||||
Blend::InvSrcAlpha,
|
||||
// DestBlendAlpha
|
||||
Operation::Add,
|
||||
// BlendOpAlpha
|
||||
ColorWrite::All,
|
||||
// RenderTargetWriteMask
|
||||
false, // AlphaToCoverageEnable
|
||||
true, // BlendEnable
|
||||
Blend::SrcAlpha, // SrcBlend
|
||||
Blend::InvSrcAlpha, // DestBlend
|
||||
Operation::Add, // BlendOp
|
||||
Blend::One, // SrcBlendAlpha
|
||||
Blend::InvSrcAlpha, // DestBlendAlpha
|
||||
Operation::Add, // BlendOpAlpha
|
||||
ColorWrite::All, // RenderTargetWriteMask
|
||||
};
|
||||
|
||||
BlendingMode BlendingMode::Add =
|
||||
{
|
||||
false,
|
||||
// AlphaToCoverageEnable
|
||||
true,
|
||||
// BlendEnable
|
||||
Blend::One,
|
||||
// SrcBlend
|
||||
Blend::One,
|
||||
// DestBlend
|
||||
Operation::Add,
|
||||
// BlendOp
|
||||
Blend::One,
|
||||
// SrcBlendAlpha
|
||||
Blend::One,
|
||||
// DestBlendAlpha
|
||||
Operation::Add,
|
||||
// BlendOpAlpha
|
||||
ColorWrite::All,
|
||||
// RenderTargetWriteMask
|
||||
false, // AlphaToCoverageEnable
|
||||
true, // BlendEnable
|
||||
Blend::One, // SrcBlend
|
||||
Blend::One, // DestBlend
|
||||
Operation::Add, // BlendOp
|
||||
Blend::One, // SrcBlendAlpha
|
||||
Blend::One, // DestBlendAlpha
|
||||
Operation::Add, // BlendOpAlpha
|
||||
ColorWrite::All, // RenderTargetWriteMask
|
||||
};
|
||||
|
||||
BlendingMode BlendingMode::Multiply =
|
||||
{
|
||||
false,
|
||||
// AlphaToCoverageEnable
|
||||
true,
|
||||
// BlendEnable
|
||||
Blend::Zero,
|
||||
// SrcBlend
|
||||
Blend::SrcColor,
|
||||
// DestBlend
|
||||
Operation::Add,
|
||||
// BlendOp
|
||||
Blend::Zero,
|
||||
// SrcBlendAlpha
|
||||
Blend::SrcAlpha,
|
||||
// DestBlendAlpha
|
||||
Operation::Add,
|
||||
// BlendOpAlpha
|
||||
ColorWrite::All,
|
||||
// RenderTargetWriteMask
|
||||
false, // AlphaToCoverageEnable
|
||||
true, // BlendEnable
|
||||
Blend::Zero, // SrcBlend
|
||||
Blend::SrcColor, // DestBlend
|
||||
Operation::Add, // BlendOp
|
||||
Blend::Zero, // SrcBlendAlpha
|
||||
Blend::SrcAlpha, // DestBlendAlpha
|
||||
Operation::Add, // BlendOpAlpha
|
||||
ColorWrite::All, // RenderTargetWriteMask
|
||||
};
|
||||
|
||||
// @formatter:on
|
||||
|
||||
FeatureLevel RenderTools::GetFeatureLevel(ShaderProfile profile)
|
||||
{
|
||||
switch (profile)
|
||||
|
||||
@@ -84,6 +84,14 @@ void RenderView::PrepareCache(const RenderContext& renderContext, float width, f
|
||||
MainScreenSize = mainView->ScreenSize;
|
||||
}
|
||||
|
||||
void RenderView::SetUp(const Matrix& viewProjection)
|
||||
{
|
||||
// Copy data
|
||||
Matrix::Invert(viewProjection, IVP);
|
||||
Frustum.SetMatrix(viewProjection);
|
||||
CullingFrustum = Frustum;
|
||||
}
|
||||
|
||||
void RenderView::SetUp(const Matrix& view, const Matrix& projection)
|
||||
{
|
||||
// Copy data
|
||||
|
||||
@@ -255,13 +255,7 @@ public:
|
||||
public:
|
||||
// Set up view with custom params
|
||||
// @param viewProjection View * Projection matrix
|
||||
void SetUp(const Matrix& viewProjection)
|
||||
{
|
||||
// Copy data
|
||||
Matrix::Invert(viewProjection, IVP);
|
||||
Frustum.SetMatrix(viewProjection);
|
||||
CullingFrustum = Frustum;
|
||||
}
|
||||
void SetUp(const Matrix& viewProjection);
|
||||
|
||||
// Set up view with custom params
|
||||
// @param view View matrix
|
||||
|
||||
@@ -103,6 +103,7 @@ void GPUContextDX11::FrameBegin()
|
||||
CurrentPS = nullptr;
|
||||
CurrentCS = nullptr;
|
||||
CurrentPrimitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
|
||||
CurrentBlendFactor = Float4::One;
|
||||
|
||||
// Bind static samplers
|
||||
ID3D11SamplerState* samplers[] =
|
||||
@@ -267,6 +268,13 @@ void GPUContextDX11::SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPU
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::SetBlendFactor(const Float4& value)
|
||||
{
|
||||
CurrentBlendFactor = value;
|
||||
if (CurrentBlendState)
|
||||
_context->OMSetBlendState(CurrentBlendState, CurrentBlendFactor.Raw, D3D11_DEFAULT_SAMPLE_MASK);
|
||||
}
|
||||
|
||||
void GPUContextDX11::ResetSR()
|
||||
{
|
||||
_srDirtyFlag = false;
|
||||
@@ -560,8 +568,7 @@ void GPUContextDX11::SetState(GPUPipelineState* state)
|
||||
if (CurrentBlendState != blendState)
|
||||
{
|
||||
CurrentBlendState = blendState;
|
||||
FLOAT blendFactor[4] = { 1, 1, 1, 1 };
|
||||
_context->OMSetBlendState(blendState, blendFactor, D3D11_DEFAULT_SAMPLE_MASK);
|
||||
_context->OMSetBlendState(blendState, CurrentBlendFactor.Raw, D3D11_DEFAULT_SAMPLE_MASK);
|
||||
}
|
||||
if (CurrentVS != vs)
|
||||
{
|
||||
|
||||
@@ -61,6 +61,7 @@ private:
|
||||
GPUShaderProgramPSDX11* CurrentPS;
|
||||
GPUShaderProgramCSDX11* CurrentCS;
|
||||
D3D11_PRIMITIVE_TOPOLOGY CurrentPrimitiveTopology;
|
||||
Float4 CurrentBlendFactor;
|
||||
|
||||
public:
|
||||
|
||||
@@ -115,6 +116,7 @@ public:
|
||||
void SetRenderTarget(GPUTextureView* rt) override;
|
||||
void SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureView* rt) override;
|
||||
void SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPUTextureView*>& rts) override;
|
||||
void SetBlendFactor(const Float4& value) override;
|
||||
void ResetSR() override;
|
||||
void ResetUA() override;
|
||||
void ResetCB() override;
|
||||
|
||||
@@ -48,7 +48,7 @@ bool GPUPipelineStateDX11::Init(const Description& desc)
|
||||
PrimitiveTopology = (D3D11_PRIMITIVE_TOPOLOGY)((int32)D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (HS->GetControlPointsCount() - 1));
|
||||
|
||||
// States
|
||||
DepthStencilStateIndex = static_cast<int32>(desc.DepthFunc) + (desc.DepthTestEnable ? 0 : 9) + (desc.DepthWriteEnable ? 0 : 18);
|
||||
DepthStencilStateIndex = static_cast<int32>(desc.DepthFunc) + (desc.DepthEnable ? 0 : 9) + (desc.DepthWriteEnable ? 0 : 18);
|
||||
RasterizerStateIndex = static_cast<int32>(desc.CullMode) + (desc.Wireframe ? 0 : 3) + (desc.DepthClipEnable ? 0 : 6);
|
||||
BlendState = _device->GetBlendState(desc.BlendMode);
|
||||
|
||||
|
||||
@@ -845,6 +845,11 @@ void GPUContextDX12::SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPU
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX12::SetBlendFactor(const Float4& value)
|
||||
{
|
||||
_commandList->OMSetBlendFactor(value.Raw);
|
||||
}
|
||||
|
||||
void GPUContextDX12::ResetSR()
|
||||
{
|
||||
for (int32 slot = 0; slot < GPU_MAX_SR_BINDED; slot++)
|
||||
|
||||
@@ -166,6 +166,7 @@ public:
|
||||
void SetRenderTarget(GPUTextureView* rt) override;
|
||||
void SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureView* rt) override;
|
||||
void SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPUTextureView*>& rts) override;
|
||||
void SetBlendFactor(const Float4& value) override;
|
||||
void ResetSR() override;
|
||||
void ResetUA() override;
|
||||
void ResetCB() override;
|
||||
|
||||
@@ -172,7 +172,7 @@ bool GPUPipelineStateDX12::Init(const Description& desc)
|
||||
}
|
||||
|
||||
// Depth State
|
||||
psDesc.DepthStencilState.DepthEnable = !!desc.DepthTestEnable;
|
||||
psDesc.DepthStencilState.DepthEnable = !!desc.DepthEnable;
|
||||
psDesc.DepthStencilState.DepthWriteMask = desc.DepthWriteEnable ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
|
||||
psDesc.DepthStencilState.DepthFunc = static_cast<D3D12_COMPARISON_FUNC>(desc.DepthFunc);
|
||||
psDesc.DepthStencilState.StencilEnable = FALSE;
|
||||
|
||||
@@ -84,6 +84,10 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void SetBlendFactor(const Float4& value) override
|
||||
{
|
||||
}
|
||||
|
||||
void ResetSR() override
|
||||
{
|
||||
}
|
||||
|
||||
@@ -966,6 +966,12 @@ void GPUContextVulkan::SetRenderTarget(GPUTextureView* depthBuffer, const Span<G
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextVulkan::SetBlendFactor(const Float4& value)
|
||||
{
|
||||
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
|
||||
vkCmdSetBlendConstants(cmdBuffer->GetHandle(), value.Raw);
|
||||
}
|
||||
|
||||
void GPUContextVulkan::ResetSR()
|
||||
{
|
||||
Platform::MemoryClear(_srHandles, sizeof(_srHandles));
|
||||
|
||||
@@ -184,6 +184,7 @@ public:
|
||||
void SetRenderTarget(GPUTextureView* rt) override;
|
||||
void SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureView* rt) override;
|
||||
void SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPUTextureView*>& rts) override;
|
||||
void SetBlendFactor(const Float4& value) override;
|
||||
void ResetSR() override;
|
||||
void ResetUA() override;
|
||||
void ResetCB() override;
|
||||
|
||||
@@ -286,7 +286,7 @@ bool GPUPipelineStateVulkan::Init(const Description& desc)
|
||||
|
||||
// Depth Stencil
|
||||
RenderToolsVulkan::ZeroStruct(_descDepthStencil, VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO);
|
||||
_descDepthStencil.depthTestEnable = desc.DepthTestEnable;
|
||||
_descDepthStencil.depthTestEnable = desc.DepthEnable;
|
||||
_descDepthStencil.depthWriteEnable = desc.DepthWriteEnable;
|
||||
_descDepthStencil.depthCompareOp = RenderToolsVulkan::ToVulkanCompareOp(desc.DepthFunc);
|
||||
_desc.pDepthStencilState = &_descDepthStencil;
|
||||
|
||||
@@ -737,6 +737,7 @@ void AnimatedModel::Draw(RenderContext& renderContext)
|
||||
draw.PerInstanceRandom = GetPerInstanceRandom();
|
||||
draw.LODBias = LODBias;
|
||||
draw.ForcedLOD = ForcedLOD;
|
||||
draw.SortOrder = SortOrder;
|
||||
|
||||
SkinnedModel->Draw(renderContext, draw);
|
||||
}
|
||||
@@ -777,6 +778,7 @@ void AnimatedModel::Draw(RenderContextBatch& renderContextBatch)
|
||||
draw.PerInstanceRandom = GetPerInstanceRandom();
|
||||
draw.LODBias = LODBias;
|
||||
draw.ForcedLOD = ForcedLOD;
|
||||
draw.SortOrder = SortOrder;
|
||||
|
||||
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
||||
if (ShadowsMode != ShadowsCastingMode::All)
|
||||
@@ -851,6 +853,7 @@ void AnimatedModel::Serialize(SerializeStream& stream, const void* otherObj)
|
||||
SERIALIZE(CustomBounds);
|
||||
SERIALIZE(LODBias);
|
||||
SERIALIZE(ForcedLOD);
|
||||
SERIALIZE(SortOrder);
|
||||
SERIALIZE(DrawModes);
|
||||
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
||||
SERIALIZE(ShadowsMode);
|
||||
@@ -877,6 +880,7 @@ void AnimatedModel::Deserialize(DeserializeStream& stream, ISerializeModifier* m
|
||||
DESERIALIZE(CustomBounds);
|
||||
DESERIALIZE(LODBias);
|
||||
DESERIALIZE(ForcedLOD);
|
||||
DESERIALIZE(SortOrder);
|
||||
DESERIALIZE(DrawModes);
|
||||
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
||||
DESERIALIZE(ShadowsMode);
|
||||
|
||||
@@ -138,6 +138,12 @@ public:
|
||||
API_FIELD(Attributes="EditorOrder(100), DefaultValue(DrawPass.Default), EditorDisplay(\"Skinned Model\")")
|
||||
DrawPass DrawModes = DrawPass::Default;
|
||||
|
||||
/// <summary>
|
||||
/// The object sort order key used when sorting drawable objects during rendering. Use lower values to draw object before others, higher values are rendered later (on top). Can be use to control transparency drawing.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorDisplay(\"Skinned Model\"), EditorOrder(110), DefaultValue(0)")
|
||||
int16 SortOrder = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The shadows casting mode.
|
||||
/// [Deprecated on 26.10.2022, expires on 26.10.2024]
|
||||
|
||||
@@ -81,7 +81,7 @@ void Sky::InitConfig(AtmosphericFogData& config) const
|
||||
|
||||
void Sky::Draw(RenderContext& renderContext)
|
||||
{
|
||||
if (HasContentLoaded())
|
||||
if (HasContentLoaded() && EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Sky))
|
||||
{
|
||||
// Ensure to have pipeline state cache created
|
||||
if (_psSky == nullptr || _psFog == nullptr)
|
||||
|
||||
@@ -40,7 +40,7 @@ void Skybox::Draw(RenderContext& renderContext)
|
||||
setupProxy();
|
||||
isReady = _proxyMaterial && _proxyMaterial->IsReady();
|
||||
}
|
||||
if (isReady)
|
||||
if (isReady && EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Sky))
|
||||
{
|
||||
renderContext.List->Sky = this;
|
||||
}
|
||||
|
||||
@@ -556,7 +556,7 @@ public:
|
||||
|
||||
// Compute particle data layout and initialize used nodes (for only used nodes, start depth searching rom the modules)
|
||||
Layout.AddAttribute(TEXT("Position"), ParticleAttribute::ValueTypes::Float3);
|
||||
#define PROCESS_MODULES(modules) for (int32 i = 0; i < modules.Count(); i++) { InitializeNode(modules[i]); }
|
||||
#define PROCESS_MODULES(modules) for (int32 i = 0; i < modules.Count(); i++) { modules[i]->Used = false; InitializeNode(modules[i]); }
|
||||
PROCESS_MODULES(SpawnModules);
|
||||
PROCESS_MODULES(InitModules);
|
||||
PROCESS_MODULES(UpdateModules);
|
||||
|
||||
@@ -258,7 +258,7 @@ void ParticleEffect::ResetSimulation()
|
||||
Instance.ClearState();
|
||||
}
|
||||
|
||||
void ParticleEffect::UpdateSimulation()
|
||||
void ParticleEffect::UpdateSimulation(bool singleFrame)
|
||||
{
|
||||
// Skip if need to
|
||||
if (!IsActiveInHierarchy()
|
||||
@@ -270,6 +270,8 @@ void ParticleEffect::UpdateSimulation()
|
||||
// Request update
|
||||
_lastUpdateFrame = Engine::FrameCount;
|
||||
_lastMinDstSqr = MAX_Real;
|
||||
if (singleFrame)
|
||||
Instance.LastUpdateTime = (UseTimeScale ? Time::Update.Time : Time::Update.UnscaledTime).GetTotalSeconds();
|
||||
Particles::UpdateEffect(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -334,7 +334,8 @@ public:
|
||||
/// <summary>
|
||||
/// Performs the full particles simulation update (postponed for the next particle manager update).
|
||||
/// </summary>
|
||||
API_FUNCTION() void UpdateSimulation();
|
||||
/// <param name="singleFrame">True if update animation by a single frame only (time time since last engine update), otherwise will update simulation with delta time since last update.</param>
|
||||
API_FUNCTION() void UpdateSimulation(bool singleFrame = false);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the actor bounds.
|
||||
|
||||
@@ -28,13 +28,13 @@
|
||||
#include "Editor/Editor.h"
|
||||
#endif
|
||||
|
||||
struct SpriteParticleVertex
|
||||
{
|
||||
PACK_STRUCT(struct SpriteParticleVertex
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
float U;
|
||||
float V;
|
||||
};
|
||||
});
|
||||
|
||||
class SpriteParticleRenderer
|
||||
{
|
||||
@@ -82,6 +82,14 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
PACK_STRUCT(struct RibbonParticleVertex {
|
||||
uint32 Order;
|
||||
uint32 ParticleIndex;
|
||||
uint32 PrevParticleIndex;
|
||||
float Distance;
|
||||
// TODO: pack into half/uint16 data
|
||||
});
|
||||
|
||||
struct EmitterCache
|
||||
{
|
||||
double LastTimeUsed;
|
||||
@@ -113,7 +121,6 @@ namespace ParticlesDrawCPU
|
||||
Array<uint32> SortingKeys[2];
|
||||
Array<int32> SortingIndices;
|
||||
Array<int32> SortedIndices;
|
||||
Array<float> RibbonTotalDistances;
|
||||
}
|
||||
|
||||
class ParticleManagerService : public EngineService
|
||||
@@ -289,14 +296,17 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
|
||||
{
|
||||
// Prepare ribbon data
|
||||
if (!buffer->GPU.RibbonIndexBufferDynamic)
|
||||
{
|
||||
buffer->GPU.RibbonIndexBufferDynamic = New<DynamicIndexBuffer>(0, (uint32)sizeof(uint16), TEXT("RibbonIndexBufferDynamic"));
|
||||
}
|
||||
buffer->GPU.RibbonIndexBufferDynamic->Clear();
|
||||
else
|
||||
buffer->GPU.RibbonIndexBufferDynamic->Clear();
|
||||
if (!buffer->GPU.RibbonVertexBufferDynamic)
|
||||
buffer->GPU.RibbonVertexBufferDynamic = New<DynamicVertexBuffer>(0, (uint32)sizeof(RibbonParticleVertex), TEXT("RibbonVertexBufferDynamic"));
|
||||
else
|
||||
buffer->GPU.RibbonVertexBufferDynamic->Clear();
|
||||
auto& indexBuffer = buffer->GPU.RibbonIndexBufferDynamic->Data;
|
||||
auto& vertexBuffer = buffer->GPU.RibbonVertexBufferDynamic->Data;
|
||||
|
||||
// Setup all ribbon modules
|
||||
auto& totalDistances = ParticlesDrawCPU::RibbonTotalDistances;
|
||||
totalDistances.Clear();
|
||||
for (int32 index = 0; index < renderModulesIndices.Count(); index++)
|
||||
{
|
||||
const int32 moduleIndex = renderModulesIndices[index];
|
||||
@@ -313,74 +323,88 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
|
||||
int32 count = buffer->CPU.Count;
|
||||
ASSERT(buffer->CPU.RibbonOrder.Count() == emitter->Graph.RibbonRenderingModules.Count() * buffer->Capacity);
|
||||
int32* ribbonOrderData = buffer->CPU.RibbonOrder.Get() + module->RibbonOrderOffset;
|
||||
|
||||
ParticleBufferCPUDataAccessor<Float3> positionData(buffer, emitter->Graph.Layout.GetAttributeOffset(module->Attributes[0]));
|
||||
|
||||
int32 indices = 0;
|
||||
|
||||
// Write ribbon indices/vertices
|
||||
int32 indices = 0, segmentCount = 0;
|
||||
float totalDistance = 0.0f;
|
||||
uint32 lastParticleIdx = ribbonOrderData[0];
|
||||
for (int32 i = 0; i < count; i++)
|
||||
int32 firstVertexIndex = vertexBuffer.Count();
|
||||
uint32 idxPrev = ribbonOrderData[0], vertexPrev = 0;
|
||||
{
|
||||
bool isNotLast = i != count - 1;
|
||||
uint32 idx0 = ribbonOrderData[i];
|
||||
uint32 idx1 = 0;
|
||||
Float3 direction;
|
||||
if (isNotLast)
|
||||
uint32 idxThis = ribbonOrderData[0];
|
||||
|
||||
// 2 vertices
|
||||
{
|
||||
idx1 = ribbonOrderData[i + 1];
|
||||
direction = positionData[idx1] - positionData[lastParticleIdx];
|
||||
}
|
||||
else
|
||||
{
|
||||
idx1 = ribbonOrderData[i - 1];
|
||||
direction = positionData[lastParticleIdx] - positionData[idx1];
|
||||
vertexBuffer.AddUninitialized(2 * sizeof(RibbonParticleVertex));
|
||||
auto ptr = (RibbonParticleVertex*)(vertexBuffer.Get() + firstVertexIndex);
|
||||
|
||||
RibbonParticleVertex v = { 0, idxThis, idxThis, totalDistance };
|
||||
|
||||
*ptr++ = v;
|
||||
*ptr++ = v;
|
||||
}
|
||||
|
||||
if (direction.LengthSquared() > 0.002f || !isNotLast)
|
||||
idxPrev = idxThis;
|
||||
}
|
||||
for (uint32 i = 1; i < count; i++)
|
||||
{
|
||||
uint32 idxThis = ribbonOrderData[i];
|
||||
Float3 direction = positionData[idxThis] - positionData[idxPrev];
|
||||
const float distance = direction.Length();
|
||||
if (distance > 0.002f)
|
||||
{
|
||||
totalDistances.Add(totalDistance);
|
||||
lastParticleIdx = idx1;
|
||||
totalDistance += distance;
|
||||
|
||||
if (isNotLast)
|
||||
// 2 vertices
|
||||
{
|
||||
auto idx = buffer->GPU.RibbonIndexBufferDynamic->Data.Count();
|
||||
buffer->GPU.RibbonIndexBufferDynamic->Data.AddDefault(6 * sizeof(uint16));
|
||||
auto ptr = (uint16*)(buffer->GPU.RibbonIndexBufferDynamic->Data.Get() + idx);
|
||||
auto idx = vertexBuffer.Count();
|
||||
vertexBuffer.AddUninitialized(2 * sizeof(RibbonParticleVertex));
|
||||
auto ptr = (RibbonParticleVertex*)(vertexBuffer.Get() + idx);
|
||||
|
||||
idx0 *= 2;
|
||||
idx1 *= 2;
|
||||
// TODO: this could be optimized by manually fetching per-particle data in vertex shader (2x less data to send and fetch)
|
||||
RibbonParticleVertex v = { i, idxThis, idxPrev, totalDistance };
|
||||
|
||||
*ptr++ = idx0 + 1;
|
||||
*ptr++ = idx1;
|
||||
*ptr++ = idx0;
|
||||
*ptr++ = v;
|
||||
*ptr++ = v;
|
||||
}
|
||||
|
||||
*ptr++ = idx0 + 1;
|
||||
*ptr++ = idx1 + 1;
|
||||
*ptr++ = idx1;
|
||||
// 2 triangles
|
||||
{
|
||||
auto idx = indexBuffer.Count();
|
||||
indexBuffer.AddUninitialized(6 * sizeof(uint16));
|
||||
auto ptr = (uint16*)(indexBuffer.Get() + idx);
|
||||
|
||||
uint32 i0 = vertexPrev;
|
||||
uint32 i1 = vertexPrev + 2;
|
||||
|
||||
*ptr++ = i0;
|
||||
*ptr++ = i0 + 1;
|
||||
*ptr++ = i1;
|
||||
|
||||
*ptr++ = i0 + 1;
|
||||
*ptr++ = i1 + 1;
|
||||
*ptr++ = i1;
|
||||
|
||||
indices += 6;
|
||||
}
|
||||
}
|
||||
|
||||
totalDistance += direction.Length();
|
||||
idxPrev = idxThis;
|
||||
segmentCount++;
|
||||
vertexPrev += 2;
|
||||
}
|
||||
}
|
||||
if (segmentCount == 0)
|
||||
continue;
|
||||
{
|
||||
// Fix first particle vertex data to have proper direction
|
||||
auto ptr0 = (RibbonParticleVertex*)(vertexBuffer.Get() + firstVertexIndex);
|
||||
auto ptr1 = ptr0 + 1;
|
||||
auto ptr2 = ptr1 + 1;
|
||||
ptr0->PrevParticleIndex = ptr1->PrevParticleIndex = ptr2->ParticleIndex;
|
||||
}
|
||||
if (indices == 0)
|
||||
break;
|
||||
|
||||
// Setup ribbon data
|
||||
ribbonModulesSegmentCount[ribbonModuleIndex] = totalDistances.Count();
|
||||
if (totalDistances.HasItems())
|
||||
{
|
||||
auto& ribbonSegmentDistancesBuffer = buffer->GPU.RibbonSegmentDistances[index];
|
||||
if (!ribbonSegmentDistancesBuffer)
|
||||
{
|
||||
ribbonSegmentDistancesBuffer = GPUDevice::Instance->CreateBuffer(TEXT("RibbonSegmentDistances"));
|
||||
ribbonSegmentDistancesBuffer->Init(GPUBufferDescription::Typed(buffer->Capacity, PixelFormat::R32_Float, false, GPUResourceUsage::Dynamic));
|
||||
}
|
||||
context->UpdateBuffer(ribbonSegmentDistancesBuffer, totalDistances.Get(), totalDistances.Count() * sizeof(float));
|
||||
}
|
||||
|
||||
ribbonModulesSegmentCount[ribbonModuleIndex] = segmentCount;
|
||||
ribbonModulesDrawIndicesCount[index] = indices;
|
||||
ribbonModulesDrawIndicesPos += indices;
|
||||
|
||||
@@ -391,6 +415,7 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
|
||||
{
|
||||
// Upload data to the GPU buffer
|
||||
buffer->GPU.RibbonIndexBufferDynamic->Flush(context);
|
||||
buffer->GPU.RibbonVertexBufferDynamic->Flush(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,13 +515,12 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
|
||||
ribbon.UVScaleX *= sortUScale;
|
||||
ribbon.UVOffsetX += sortUOffset * uvScale.X;
|
||||
}
|
||||
ribbon.SegmentDistances = ribbon.SegmentCount != 0 ? buffer->GPU.RibbonSegmentDistances[index] : nullptr;
|
||||
|
||||
// TODO: invert particles rendering order if camera is closer to the ribbon end than start
|
||||
|
||||
// Submit draw call
|
||||
drawCall.Geometry.IndexBuffer = buffer->GPU.RibbonIndexBufferDynamic->GetBuffer();
|
||||
drawCall.Geometry.VertexBuffers[0] = nullptr;
|
||||
drawCall.Geometry.VertexBuffers[0] = buffer->GPU.RibbonVertexBufferDynamic->GetBuffer();
|
||||
drawCall.Geometry.VertexBuffers[1] = nullptr;
|
||||
drawCall.Geometry.VertexBuffers[2] = nullptr;
|
||||
drawCall.Geometry.VertexBuffersOffsets[0] = 0;
|
||||
@@ -1187,7 +1211,6 @@ void ParticleManagerService::Dispose()
|
||||
ParticlesDrawCPU::SortingKeys[1].SetCapacity(0);
|
||||
ParticlesDrawCPU::SortingIndices.SetCapacity(0);
|
||||
ParticlesDrawCPU::SortedIndices.SetCapacity(0);
|
||||
ParticlesDrawCPU::RibbonTotalDistances.SetCapacity(0);
|
||||
|
||||
PoolLocker.Lock();
|
||||
for (auto i = Pool.Begin(); i.IsNotEnd(); ++i)
|
||||
|
||||
@@ -18,8 +18,7 @@ ParticleBuffer::~ParticleBuffer()
|
||||
SAFE_DELETE_GPU_RESOURCE(GPU.SortingKeysBuffer);
|
||||
SAFE_DELETE_GPU_RESOURCE(GPU.SortedIndices);
|
||||
SAFE_DELETE(GPU.RibbonIndexBufferDynamic);
|
||||
for (auto& e : GPU.RibbonSegmentDistances)
|
||||
SAFE_DELETE_GPU_RESOURCE(e);
|
||||
SAFE_DELETE(GPU.RibbonVertexBufferDynamic);
|
||||
}
|
||||
|
||||
bool ParticleBuffer::Init(ParticleEmitter* emitter)
|
||||
|
||||
@@ -17,6 +17,7 @@ class ParticleEmitter;
|
||||
class Particles;
|
||||
class GPUBuffer;
|
||||
class DynamicIndexBuffer;
|
||||
class DynamicVertexBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// The particle attribute that defines a single particle layout component.
|
||||
@@ -302,9 +303,9 @@ public:
|
||||
DynamicIndexBuffer* RibbonIndexBufferDynamic = nullptr;
|
||||
|
||||
/// <summary>
|
||||
/// The ribbon particles rendering segment distances buffer. Stored one per ribbon module.
|
||||
/// The ribbon particles rendering vertex buffer (dynamic GPU access).
|
||||
/// </summary>
|
||||
GPUBuffer* RibbonSegmentDistances[PARTICLE_EMITTER_MAX_RIBBONS] = {};
|
||||
DynamicVertexBuffer* RibbonVertexBufferDynamic = nullptr;
|
||||
|
||||
/// <summary>
|
||||
/// The flag used to indicate that GPU buffers data should be cleared before next simulation.
|
||||
|
||||
@@ -481,7 +481,7 @@ bool CachedPSO::Init(GPUShader* shader, bool useDepth)
|
||||
|
||||
// Create pipeline states
|
||||
GPUPipelineState::Description desc = GPUPipelineState::Description::DefaultFullscreenTriangle;
|
||||
desc.DepthTestEnable = desc.DepthWriteEnable = useDepth;
|
||||
desc.DepthEnable = desc.DepthWriteEnable = useDepth;
|
||||
desc.DepthWriteEnable = false;
|
||||
desc.DepthClipEnable = false;
|
||||
desc.VS = shader->GetVS("VS");
|
||||
|
||||
@@ -62,7 +62,7 @@ bool ColorGradingPass::Init()
|
||||
formatSupportFlags |= FormatSupport::Texture3D;
|
||||
else
|
||||
formatSupportFlags |= FormatSupport::Texture2D;
|
||||
if (!EnumHasAllFlags(formatSupport, formatSupportFlags))
|
||||
if (EnumHasNoneFlags(formatSupport, formatSupportFlags))
|
||||
{
|
||||
// Fallback to format that is supported on every washing machine
|
||||
_lutFormat = PixelFormat::R8G8B8A8_UNorm;
|
||||
|
||||
@@ -117,6 +117,3 @@ PACK_STRUCT(struct ProbeData {
|
||||
|
||||
// Default format for the shadow map textures
|
||||
#define SHADOW_MAPS_FORMAT PixelFormat::D16_UNorm
|
||||
|
||||
// Material distortion offsets output pass (material uses PS_Distortion, ForwardPass resolves the offsets)
|
||||
#define Distortion_Pass_Output_Format PixelFormat::R8G8B8A8_UNorm
|
||||
|
||||
@@ -221,7 +221,6 @@ struct DrawCall
|
||||
float UVOffsetX;
|
||||
float UVOffsetY;
|
||||
uint32 SegmentCount;
|
||||
GPUBuffer* SegmentDistances;
|
||||
} Ribbon;
|
||||
|
||||
struct
|
||||
|
||||
@@ -107,7 +107,7 @@ void ForwardPass::Render(RenderContext& renderContext, GPUTexture* input, GPUTex
|
||||
const int32 height = renderContext.Buffers->GetHeight();
|
||||
const int32 distortionWidth = width;
|
||||
const int32 distortionHeight = height;
|
||||
const auto tempDesc = GPUTextureDescription::New2D(distortionWidth, distortionHeight, Distortion_Pass_Output_Format);
|
||||
const auto tempDesc = GPUTextureDescription::New2D(distortionWidth, distortionHeight, PixelFormat::R8G8B8A8_UNorm);
|
||||
auto distortionRT = RenderTargetPool::Get(tempDesc);
|
||||
RENDER_TARGET_POOL_SET_NAME(distortionRT, "Forward.Distortion");
|
||||
|
||||
@@ -119,15 +119,13 @@ void ForwardPass::Render(RenderContext& renderContext, GPUTexture* input, GPUTex
|
||||
// Render distortion pass
|
||||
view.Pass = DrawPass::Distortion;
|
||||
mainCache->ExecuteDrawCalls(renderContext, distortionList);
|
||||
|
||||
// Copy combined frame with distortion from transparent materials
|
||||
context->SetViewportAndScissors((float)width, (float)height);
|
||||
context->ResetRenderTarget();
|
||||
context->ResetSR();
|
||||
|
||||
// Bind inputs
|
||||
context->BindSR(0, input);
|
||||
context->BindSR(1, distortionRT);
|
||||
|
||||
// Copy combined frame with distortion from transparent materials
|
||||
context->SetRenderTarget(output->View());
|
||||
context->SetState(_psApplyDistortion);
|
||||
context->DrawFullscreenTriangle();
|
||||
|
||||
@@ -146,7 +146,7 @@ void DebugOverrideDrawCallsMaterial(const RenderContext& renderContext, IMateria
|
||||
|
||||
#endif
|
||||
|
||||
void GBufferPass::Fill(RenderContext& renderContext, GPUTextureView* lightBuffer)
|
||||
void GBufferPass::Fill(RenderContext& renderContext, GPUTexture* lightBuffer)
|
||||
{
|
||||
PROFILE_GPU_CPU("GBuffer");
|
||||
|
||||
@@ -155,7 +155,7 @@ void GBufferPass::Fill(RenderContext& renderContext, GPUTextureView* lightBuffer
|
||||
auto context = device->GetMainContext();
|
||||
GPUTextureView* targetBuffers[5] =
|
||||
{
|
||||
lightBuffer,
|
||||
lightBuffer->View(),
|
||||
renderContext.Buffers->GBuffer0->View(),
|
||||
renderContext.Buffers->GBuffer1->View(),
|
||||
renderContext.Buffers->GBuffer2->View(),
|
||||
@@ -168,7 +168,7 @@ void GBufferPass::Fill(RenderContext& renderContext, GPUTextureView* lightBuffer
|
||||
PROFILE_GPU_CPU_NAMED("Clear");
|
||||
|
||||
context->ClearDepth(*renderContext.Buffers->DepthBuffer);
|
||||
context->Clear(lightBuffer, Color::Transparent);
|
||||
context->Clear(lightBuffer->View(), Color::Transparent);
|
||||
context->Clear(renderContext.Buffers->GBuffer0->View(), Color::Transparent);
|
||||
context->Clear(renderContext.Buffers->GBuffer1->View(), Color::Transparent);
|
||||
context->Clear(renderContext.Buffers->GBuffer2->View(), Color(1, 0, 0, 0));
|
||||
@@ -192,7 +192,7 @@ void GBufferPass::Fill(RenderContext& renderContext, GPUTextureView* lightBuffer
|
||||
renderContext.List->Sky->ApplySky(context, renderContext, Matrix::Identity);
|
||||
GPUPipelineState* materialPs = context->GetState();
|
||||
const float complexity = (float)Math::Min(materialPs->Complexity, MATERIAL_COMPLEXITY_LIMIT) / MATERIAL_COMPLEXITY_LIMIT;
|
||||
context->Clear(lightBuffer, Color(complexity, complexity, complexity, 1.0f));
|
||||
context->Clear(lightBuffer->View(), Color(complexity, complexity, complexity, 1.0f));
|
||||
renderContext.List->Sky = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -208,16 +208,20 @@ void GBufferPass::Fill(RenderContext& renderContext, GPUTextureView* lightBuffer
|
||||
renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::GBuffer);
|
||||
|
||||
// Draw decals
|
||||
DrawDecals(renderContext, lightBuffer);
|
||||
DrawDecals(renderContext, lightBuffer->View());
|
||||
|
||||
// Draw objects that cannot get decals
|
||||
context->SetRenderTarget(*renderContext.Buffers->DepthBuffer, ToSpan(targetBuffers, ARRAY_COUNT(targetBuffers)));
|
||||
renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::GBufferNoDecals);
|
||||
|
||||
GPUTexture* nullTexture = nullptr;
|
||||
renderContext.List->RunCustomPostFxPass(context, renderContext, PostProcessEffectLocation::AfterGBufferPass, lightBuffer, nullTexture);
|
||||
|
||||
// Draw sky
|
||||
if (renderContext.List->Sky && _skyModel && _skyModel->CanBeRendered())
|
||||
if (renderContext.List->Sky && _skyModel && _skyModel->CanBeRendered() && EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Sky))
|
||||
{
|
||||
PROFILE_GPU_CPU_NAMED("Sky");
|
||||
context->SetRenderTarget(*renderContext.Buffers->DepthBuffer, ToSpan(targetBuffers, ARRAY_COUNT(targetBuffers)));
|
||||
DrawSky(renderContext, context);
|
||||
}
|
||||
|
||||
@@ -279,7 +283,7 @@ public:
|
||||
GPUTextureView* GBufferPass::RenderSkybox(RenderContext& renderContext, GPUContext* context)
|
||||
{
|
||||
GPUTextureView* result = nullptr;
|
||||
if (renderContext.List->Sky && _skyModel && _skyModel->CanBeRendered())
|
||||
if (renderContext.List->Sky && _skyModel && _skyModel->CanBeRendered() && EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Sky))
|
||||
{
|
||||
// Initialize skybox texture
|
||||
auto& skyboxData = *renderContext.Buffers->GetCustomBuffer<SkyboxCustomBuffer>(TEXT("Skybox"));
|
||||
@@ -426,7 +430,7 @@ void GBufferPass::DrawDecals(RenderContext& renderContext, GPUTextureView* light
|
||||
{
|
||||
// Skip if no decals to render
|
||||
auto& decals = renderContext.List->Decals;
|
||||
if (decals.IsEmpty() || _boxModel == nullptr || !_boxModel->CanBeRendered())
|
||||
if (decals.IsEmpty() || _boxModel == nullptr || !_boxModel->CanBeRendered() || EnumHasNoneFlags(renderContext.View.Flags, ViewFlags::Decals))
|
||||
return;
|
||||
|
||||
PROFILE_GPU_CPU("Decals");
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="renderContext">The rendering context.</param>
|
||||
/// <param name="lightBuffer">Light buffer to output material emissive light and precomputed indirect lighting</param>
|
||||
void Fill(RenderContext& renderContext, GPUTextureView* lightBuffer);
|
||||
void Fill(RenderContext& renderContext, GPUTexture* lightBuffer);
|
||||
|
||||
/// <summary>
|
||||
/// Render debug view
|
||||
|
||||
@@ -284,7 +284,7 @@ bool GlobalSurfaceAtlasPass::setupResources()
|
||||
if (!_psClear)
|
||||
{
|
||||
_psClear = device->CreatePipelineState();
|
||||
psDesc.DepthTestEnable = true;
|
||||
psDesc.DepthEnable = true;
|
||||
psDesc.DepthWriteEnable = true;
|
||||
psDesc.DepthFunc = ComparisonFunc::Always;
|
||||
psDesc.VS = shader->GetVS("VS_Atlas");
|
||||
@@ -292,7 +292,7 @@ bool GlobalSurfaceAtlasPass::setupResources()
|
||||
if (_psClear->Init(psDesc))
|
||||
return true;
|
||||
}
|
||||
psDesc.DepthTestEnable = false;
|
||||
psDesc.DepthEnable = false;
|
||||
psDesc.DepthWriteEnable = false;
|
||||
psDesc.DepthFunc = ComparisonFunc::Never;
|
||||
if (!_psClearLighting)
|
||||
|
||||
@@ -50,7 +50,7 @@ bool LightPass::Init()
|
||||
#endif
|
||||
|
||||
auto format = PixelFormat::R8G8_UNorm;
|
||||
if (!EnumHasAllFlags(GPUDevice::Instance->GetFormatFeatures(format).Support, (FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D)))
|
||||
if (EnumHasNoneFlags(GPUDevice::Instance->GetFormatFeatures(format).Support, (FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D)))
|
||||
{
|
||||
format = PixelFormat::B8G8R8A8_UNorm;
|
||||
}
|
||||
@@ -98,7 +98,7 @@ bool LightPass::setupResources()
|
||||
if (_psLightPointInverted.Create(psDesc, shader, "PS_Point"))
|
||||
return true;
|
||||
psDesc.CullMode = CullMode::Normal;
|
||||
psDesc.DepthTestEnable = true;
|
||||
psDesc.DepthEnable = true;
|
||||
if (_psLightPointNormal.Create(psDesc, shader, "PS_Point"))
|
||||
return true;
|
||||
}
|
||||
@@ -112,7 +112,7 @@ bool LightPass::setupResources()
|
||||
if (_psLightSpotInverted.Create(psDesc, shader, "PS_Spot"))
|
||||
return true;
|
||||
psDesc.CullMode = CullMode::Normal;
|
||||
psDesc.DepthTestEnable = true;
|
||||
psDesc.DepthEnable = true;
|
||||
if (_psLightSpotNormal.Create(psDesc, shader, "PS_Spot"))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -62,11 +62,11 @@ bool MotionBlurPass::Init()
|
||||
|
||||
// Prepare formats for the buffers
|
||||
auto format = PixelFormat::R16G16_Float;
|
||||
if (!EnumHasAllFlags(GPUDevice::Instance->GetFormatFeatures(format).Support, FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D))
|
||||
if (EnumHasNoneFlags(GPUDevice::Instance->GetFormatFeatures(format).Support, FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D))
|
||||
{
|
||||
if (!EnumHasAllFlags(GPUDevice::Instance->GetFormatFeatures(PixelFormat::R32G32_Float).Support, FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D))
|
||||
if (EnumHasNoneFlags(GPUDevice::Instance->GetFormatFeatures(PixelFormat::R32G32_Float).Support, FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D))
|
||||
format = PixelFormat::R32G32_Float;
|
||||
else if (!EnumHasAllFlags(GPUDevice::Instance->GetFormatFeatures(PixelFormat::R16G16B16A16_Float).Support, FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D))
|
||||
else if (EnumHasNoneFlags(GPUDevice::Instance->GetFormatFeatures(PixelFormat::R16G16B16A16_Float).Support, FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D))
|
||||
format = PixelFormat::R16G16B16A16_Float;
|
||||
else
|
||||
format = PixelFormat::R32G32B32A32_Float;
|
||||
|
||||
@@ -181,24 +181,13 @@ void PostProcessingPass::Dispose()
|
||||
|
||||
void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input, GPUTexture* output, GPUTexture* colorGradingLUT)
|
||||
{
|
||||
PROFILE_GPU_CPU("Post Processing");
|
||||
auto device = GPUDevice::Instance;
|
||||
auto context = device->GetMainContext();
|
||||
auto& view = renderContext.View;
|
||||
|
||||
PROFILE_GPU_CPU("Post Processing");
|
||||
|
||||
|
||||
context->ResetRenderTarget();
|
||||
|
||||
// Ensure to have valid data
|
||||
if (checkIfSkipPass())
|
||||
{
|
||||
// Resources are missing. Do not perform rendering. Just copy raw frame
|
||||
context->SetRenderTarget(*output);
|
||||
context->Draw(input);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cache data
|
||||
PostProcessSettings& settings = renderContext.List->Settings;
|
||||
bool useBloom = EnumHasAnyFlags(view.Flags, ViewFlags::Bloom) && settings.Bloom.Enabled && settings.Bloom.Intensity > 0.0f;
|
||||
bool useToneMapping = EnumHasAnyFlags(view.Flags, ViewFlags::ToneMapping);
|
||||
@@ -206,9 +195,10 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input,
|
||||
bool useLensFlares = EnumHasAnyFlags(view.Flags, ViewFlags::LensFlares) && settings.LensFlares.Intensity > 0.0f && useBloom;
|
||||
|
||||
// Ensure to have valid data and if at least one effect should be applied
|
||||
if (!(useBloom || useToneMapping || useCameraArtifacts))
|
||||
if (checkIfSkipPass() || !(useBloom || useToneMapping || useCameraArtifacts))
|
||||
{
|
||||
// Resources are missing. Do not perform rendering. Just copy raw frame
|
||||
context->SetViewportAndScissors(output->Width(), output->Height());
|
||||
context->SetRenderTarget(*output);
|
||||
context->Draw(input);
|
||||
return;
|
||||
|
||||
@@ -268,6 +268,7 @@ bool ProbesRenderer::Init()
|
||||
ViewFlags::SkyLights |
|
||||
ViewFlags::Decals |
|
||||
ViewFlags::Shadows |
|
||||
ViewFlags::Sky |
|
||||
ViewFlags::Fog;
|
||||
view.Mode = ViewMode::NoPostFx;
|
||||
view.IsOfflinePass = true;
|
||||
|
||||
@@ -265,7 +265,7 @@ void RenderList::RunPostFxPass(GPUContext* context, RenderContext& renderContext
|
||||
{
|
||||
if (fx->Location == locationB)
|
||||
{
|
||||
if (fx->UseSingleTarget)
|
||||
if (fx->UseSingleTarget || output == nullptr)
|
||||
{
|
||||
fx->Render(context, renderContext, input, nullptr);
|
||||
}
|
||||
@@ -298,9 +298,9 @@ void RenderList::RunMaterialPostFxPass(GPUContext* context, RenderContext& rende
|
||||
bindParams.Input = *input;
|
||||
material->Bind(bindParams);
|
||||
context->DrawFullscreenTriangle();
|
||||
context->ResetRenderTarget();
|
||||
Swap(output, input);
|
||||
}
|
||||
context->ResetRenderTarget();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,7 +312,7 @@ void RenderList::RunCustomPostFxPass(GPUContext* context, RenderContext& renderC
|
||||
{
|
||||
if (fx->Location == location)
|
||||
{
|
||||
if (fx->UseSingleTarget)
|
||||
if (fx->UseSingleTarget || output == nullptr)
|
||||
{
|
||||
fx->Render(context, renderContext, input, nullptr);
|
||||
}
|
||||
|
||||
@@ -236,24 +236,7 @@ void Renderer::DrawSceneDepth(GPUContext* context, SceneRenderTask* task, GPUTex
|
||||
renderContext.View.Prepare(renderContext);
|
||||
|
||||
// Call drawing (will collect draw calls)
|
||||
if (customActors.HasItems())
|
||||
{
|
||||
// Draw custom actors
|
||||
for (auto actor : customActors)
|
||||
{
|
||||
if (actor && actor->GetIsActive())
|
||||
actor->Draw(renderContext);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw scene actors
|
||||
RenderContextBatch renderContextBatch(renderContext);
|
||||
Level::DrawActors(renderContextBatch);
|
||||
for (const int64 label : renderContextBatch.WaitLabels)
|
||||
JobSystem::Wait(label);
|
||||
renderContextBatch.WaitLabels.Clear();
|
||||
}
|
||||
DrawActors(renderContext, customActors);
|
||||
|
||||
// Sort draw calls
|
||||
renderContext.List->SortDrawCalls(renderContext, false, DrawCallsListType::Depth);
|
||||
@@ -287,6 +270,31 @@ void Renderer::DrawPostFxMaterial(GPUContext* context, const RenderContext& rend
|
||||
context->ResetRenderTarget();
|
||||
}
|
||||
|
||||
void Renderer::DrawActors(RenderContext& renderContext, const Array<Actor*>& customActors)
|
||||
{
|
||||
if (customActors.HasItems())
|
||||
{
|
||||
// Draw custom actors
|
||||
for (Actor* actor : customActors)
|
||||
{
|
||||
if (actor && actor->GetIsActive())
|
||||
actor->Draw(renderContext);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw scene actors
|
||||
RenderContextBatch renderContextBatch(renderContext);
|
||||
JobSystem::SetJobStartingOnDispatch(false);
|
||||
Level::DrawActors(renderContextBatch, SceneRendering::DrawCategory::SceneDraw);
|
||||
Level::DrawActors(renderContextBatch, SceneRendering::DrawCategory::SceneDrawAsync);
|
||||
JobSystem::SetJobStartingOnDispatch(true);
|
||||
for (const int64 label : renderContextBatch.WaitLabels)
|
||||
JobSystem::Wait(label);
|
||||
renderContextBatch.WaitLabels.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderContextBatch& renderContextBatch)
|
||||
{
|
||||
auto context = GPUDevice::Instance->GetMainContext();
|
||||
@@ -304,6 +312,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
|
||||
|
||||
// Initialize setup
|
||||
RenderSetup& setup = renderContext.List->Setup;
|
||||
const bool isGBufferDebug = GBufferPass::IsDebugView(renderContext.View.Mode);
|
||||
{
|
||||
PROFILE_CPU_NAMED("Setup");
|
||||
if (renderContext.View.Origin != renderContext.View.PrevOrigin)
|
||||
@@ -311,7 +320,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
|
||||
const int32 screenWidth = renderContext.Buffers->GetWidth();
|
||||
const int32 screenHeight = renderContext.Buffers->GetHeight();
|
||||
setup.UpscaleLocation = renderContext.Task->UpscaleLocation;
|
||||
if (screenWidth < 16 || screenHeight < 16 || renderContext.Task->IsCameraCut)
|
||||
if (screenWidth < 16 || screenHeight < 16 || renderContext.Task->IsCameraCut || isGBufferDebug || renderContext.View.Mode == ViewMode::NoPostFx)
|
||||
setup.UseMotionVectors = false;
|
||||
else
|
||||
{
|
||||
@@ -336,7 +345,6 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
|
||||
renderContext.Buffers->Prepare();
|
||||
|
||||
// Build batch of render contexts (main view and shadow projections)
|
||||
const bool isGBufferDebug = GBufferPass::IsDebugView(renderContext.View.Mode);
|
||||
{
|
||||
PROFILE_CPU_NAMED("Collect Draw Calls");
|
||||
|
||||
@@ -423,7 +431,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
|
||||
}
|
||||
|
||||
// Fill GBuffer
|
||||
GBufferPass::Instance()->Fill(renderContext, lightBuffer->View());
|
||||
GBufferPass::Instance()->Fill(renderContext, lightBuffer);
|
||||
|
||||
// Debug drawing
|
||||
if (renderContext.View.Mode == ViewMode::GlobalSDF)
|
||||
@@ -537,6 +545,10 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
|
||||
RENDER_TARGET_POOL_SET_NAME(frameBuffer, "FrameBuffer");
|
||||
ForwardPass::Instance()->Render(renderContext, lightBuffer, frameBuffer);
|
||||
|
||||
// Material and Custom PostFx
|
||||
renderContext.List->RunMaterialPostFxPass(context, renderContext, MaterialPostFxLocation::AfterForwardPass, frameBuffer, lightBuffer);
|
||||
renderContext.List->RunCustomPostFxPass(context, renderContext, PostProcessEffectLocation::AfterForwardPass, frameBuffer, lightBuffer);
|
||||
|
||||
// Cleanup
|
||||
context->ResetRenderTarget();
|
||||
context->ResetSR();
|
||||
|
||||
@@ -13,9 +13,21 @@ namespace FlaxEngine
|
||||
/// <param name="task">Render task to use it's view description and the render buffers.</param>
|
||||
/// <param name="output">The output texture. Must be valid and created.</param>
|
||||
/// <param name="customActors">The custom set of actors to render. If empty, the loaded scenes will be rendered.</param>
|
||||
[Unmanaged]
|
||||
public static void DrawSceneDepth(GPUContext context, SceneRenderTask task, GPUTexture output, List<Actor> customActors)
|
||||
{
|
||||
Internal_DrawSceneDepth(FlaxEngine.Object.GetUnmanagedPtr(context), FlaxEngine.Object.GetUnmanagedPtr(task), FlaxEngine.Object.GetUnmanagedPtr(output), Utils.ExtractArrayFromList(customActors));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked drawing of the scene objects (collects draw calls into RenderList for a given RenderContext).
|
||||
/// </summary>
|
||||
/// <param name="renderContext">The rendering context.</param>
|
||||
/// <param name="customActors">The custom set of actors to render. If empty, the loaded scenes will be rendered.</param>
|
||||
[Unmanaged]
|
||||
public static void DrawActors(ref RenderContext renderContext, List<Actor> customActors)
|
||||
{
|
||||
Internal_DrawActors(ref renderContext, Utils.ExtractArrayFromList(customActors));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,22 +18,18 @@ class Actor;
|
||||
/// </summary>
|
||||
API_CLASS(Static) class FLAXENGINE_API Renderer
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_NO_SPAWN(Renderer);
|
||||
DECLARE_SCRIPTING_TYPE_NO_SPAWN(Renderer);
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the scene rendering system is ready (all shaders are loaded and helper resources are ready).
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if this rendering service is ready for scene rendering; otherwise, <c>false</c>.</returns>
|
||||
static bool IsReady();
|
||||
|
||||
/// <summary>
|
||||
/// Performs rendering for the input task.
|
||||
/// </summary>
|
||||
/// <param name="task">The scene rendering task.</param>
|
||||
static void Render(SceneRenderTask* task);
|
||||
|
||||
public:
|
||||
API_FUNCTION() static void Render(SceneRenderTask* task);
|
||||
|
||||
/// <summary>
|
||||
/// Draws scene objects depth (to the output Z buffer). The output must be depth texture to write hardware depth to it.
|
||||
@@ -53,4 +49,11 @@ public:
|
||||
/// <param name="output">The output texture. Must be valid and created.</param>
|
||||
/// <param name="input">The input texture. It's optional.</param>
|
||||
API_FUNCTION() static void DrawPostFxMaterial(GPUContext* context, API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, GPUTexture* output, GPUTextureView* input);
|
||||
|
||||
/// <summary>
|
||||
/// Invoked drawing of the scene objects (collects draw calls into RenderList for a given RenderContext).
|
||||
/// </summary>
|
||||
/// <param name="renderContext">The rendering context.</param>
|
||||
/// <param name="customActors">The custom set of actors to render. If empty, the loaded scenes will be rendered.</param>
|
||||
API_FUNCTION() static void DrawActors(API_PARAM(Ref) RenderContext& renderContext, API_PARAM(DefaultValue=null) const Array<Actor*, HeapAllocation>& customActors);
|
||||
};
|
||||
|
||||
@@ -76,7 +76,7 @@ bool MultiScaler::setupResources()
|
||||
{
|
||||
psDesc.PS = shader->GetPS("PS_HalfDepth");
|
||||
psDesc.DepthWriteEnable = true;
|
||||
psDesc.DepthTestEnable = true;
|
||||
psDesc.DepthEnable = true;
|
||||
psDesc.DepthFunc = ComparisonFunc::Always;
|
||||
if (_psHalfDepth->Init(psDesc))
|
||||
return true;
|
||||
|
||||
@@ -448,6 +448,7 @@ bool ShadowsOfMordor::Builder::initResources()
|
||||
ViewFlags::DirectionalLights |
|
||||
ViewFlags::PointLights |
|
||||
ViewFlags::SpotLights |
|
||||
ViewFlags::Sky |
|
||||
ViewFlags::Shadows |
|
||||
ViewFlags::Decals |
|
||||
ViewFlags::SkyLights |
|
||||
|
||||
@@ -31,6 +31,7 @@ MaterialGenerator::MaterialGraphBoxesMapping MaterialGenerator::MaterialGraphBox
|
||||
|
||||
const MaterialGenerator::MaterialGraphBoxesMapping& MaterialGenerator::GetMaterialRootNodeBox(MaterialGraphBoxes box)
|
||||
{
|
||||
static_assert(ARRAY_COUNT(MaterialGenerator::MaterialGraphBoxesMappings) == 15, "Invalid amount of boxes added for root node. Please update the code above");
|
||||
return MaterialGraphBoxesMappings[static_cast<int32>(box)];
|
||||
}
|
||||
|
||||
|
||||
@@ -252,6 +252,7 @@ void MaterialGenerator::ProcessGroupLayers(Box* box, Node* node, Value& value)
|
||||
CHECK_MATERIAL_FEATURE(Emissive, UseEmissive);
|
||||
CHECK_MATERIAL_FEATURE(Normal, UseNormal);
|
||||
CHECK_MATERIAL_FEATURE(Mask, UseMask);
|
||||
CHECK_MATERIAL_FEATURE(Refraction, UseRefraction);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include "Engine/Graphics/Materials/MaterialInfo.h"
|
||||
#include "Engine/Graphics/Materials/MaterialParams.h"
|
||||
#include "Engine/Content/AssetsContainer.h"
|
||||
#include "MaterialLayer.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
@@ -170,11 +170,11 @@ MaterialLayer* MaterialLayer::Load(const Guid& id, ReadStream* graphData, const
|
||||
LOG(Warning, "Missing root node in '{0}'.", caller);
|
||||
layer->createRootNode();
|
||||
}
|
||||
// Ensure to have valid root node
|
||||
else if (layer->Root->Boxes.Count() != static_cast<int32>(MaterialGraphBoxes::MAX))
|
||||
// Ensure to have valid root node
|
||||
else if (layer->Root->Boxes.Count() < static_cast<int32>(MaterialGraphBoxes::MAX))
|
||||
{
|
||||
#define ADD_BOX(type, valueType) \
|
||||
if(layer->Root->Boxes.Count() <= static_cast<int32>(MaterialGraphBoxes::type)) \
|
||||
if (layer->Root->Boxes.Count() <= static_cast<int32>(MaterialGraphBoxes::type)) \
|
||||
layer->Root->Boxes.Add(MaterialGraphBox(layer->Root, static_cast<int32>(MaterialGraphBoxes::type), VariantType::valueType))
|
||||
ADD_BOX(TessellationMultiplier, Float);
|
||||
ADD_BOX(WorldDisplacement, Float3);
|
||||
|
||||
Reference in New Issue
Block a user