diff --git a/Source/Engine/Graphics/GPUContext.h b/Source/Engine/Graphics/GPUContext.h
index 593282555..99a226193 100644
--- a/Source/Engine/Graphics/GPUContext.h
+++ b/Source/Engine/Graphics/GPUContext.h
@@ -315,6 +315,12 @@ public:
/// The array with render targets to bind.
API_FUNCTION() virtual void SetRenderTarget(GPUTextureView* depthBuffer, const Span& rts) = 0;
+ ///
+ /// Sets the blend factor that modulate values for a pixel shader, render target, or both.
+ ///
+ /// Blend factors, one for each RGBA component.
+ API_FUNCTION() virtual void SetBlendFactor(const Float4& value) = 0;
+
public:
///
/// 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).
diff --git a/Source/Engine/Graphics/RenderTools.cpp b/Source/Engine/Graphics/RenderTools.cpp
index 67cbce85b..8389e5d3c 100644
--- a/Source/Engine/Graphics/RenderTools.cpp
+++ b/Source/Engine/Graphics/RenderTools.cpp
@@ -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)
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp
index 06f666e12..2ac639e30 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp
@@ -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 SpanOMSetBlendState(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)
{
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.h b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.h
index 209968fda..b623cba3b 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.h
+++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.h
@@ -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& rts) override;
+ void SetBlendFactor(const Float4& value) override;
void ResetSR() override;
void ResetUA() override;
void ResetCB() override;
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp
index b8af1178b..54f1a4290 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp
@@ -845,6 +845,11 @@ void GPUContextDX12::SetRenderTarget(GPUTextureView* depthBuffer, const SpanOMSetBlendFactor(value.Raw);
+}
+
void GPUContextDX12::ResetSR()
{
for (int32 slot = 0; slot < GPU_MAX_SR_BINDED; slot++)
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.h b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.h
index 4ab6c9155..c870cf71e 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.h
+++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.h
@@ -166,6 +166,7 @@ public:
void SetRenderTarget(GPUTextureView* rt) override;
void SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureView* rt) override;
void SetRenderTarget(GPUTextureView* depthBuffer, const Span& rts) override;
+ void SetBlendFactor(const Float4& value) override;
void ResetSR() override;
void ResetUA() override;
void ResetCB() override;
diff --git a/Source/Engine/GraphicsDevice/Null/GPUContextNull.h b/Source/Engine/GraphicsDevice/Null/GPUContextNull.h
index a1ffc290a..7568bb60c 100644
--- a/Source/Engine/GraphicsDevice/Null/GPUContextNull.h
+++ b/Source/Engine/GraphicsDevice/Null/GPUContextNull.h
@@ -84,6 +84,10 @@ public:
{
}
+ void SetBlendFactor(const Float4& value) override
+ {
+ }
+
void ResetSR() override
{
}
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp
index 5c13dd896..d52b446e3 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp
@@ -966,6 +966,12 @@ void GPUContextVulkan::SetRenderTarget(GPUTextureView* depthBuffer, const SpanGetCmdBuffer();
+ vkCmdSetBlendConstants(cmdBuffer->GetHandle(), value.Raw);
+}
+
void GPUContextVulkan::ResetSR()
{
Platform::MemoryClear(_srHandles, sizeof(_srHandles));
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.h
index 2b8d9f122..63224b2d0 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.h
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.h
@@ -184,6 +184,7 @@ public:
void SetRenderTarget(GPUTextureView* rt) override;
void SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureView* rt) override;
void SetRenderTarget(GPUTextureView* depthBuffer, const Span& rts) override;
+ void SetBlendFactor(const Float4& value) override;
void ResetSR() override;
void ResetUA() override;
void ResetCB() override;