Reenable LyShine mask support now using Atom (#1218)

* Add option to set stencil ref in Dynamic Draw Context

* Add depth/stencil attachment slot to UI pass

* Rework mask rendering to use Atom

* Add missing circle mask image
main
michabr 5 years ago committed by GitHub
parent 0c7605c9b6
commit 6584e1290b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -322,7 +322,14 @@
"Pass": "AuxGeomPass", "Pass": "AuxGeomPass",
"Attachment": "ColorInputOutput" "Attachment": "ColorInputOutput"
} }
} },
{
"LocalSlot": "DepthInputOutput",
"AttachmentRef": {
"Pass": "DepthPrePass",
"Attachment": "Depth"
}
}
] ]
}, },
{ {

@ -427,6 +427,13 @@
"Pass": "DebugOverlayPass", "Pass": "DebugOverlayPass",
"Attachment": "InputOutput" "Attachment": "InputOutput"
} }
},
{
"LocalSlot": "DepthInputOutput",
"AttachmentRef": {
"Pass": "DepthPrePass",
"Attachment": "Depth"
}
} }
] ]
}, },

@ -7,6 +7,23 @@
"Name": "UIPassTemplate", "Name": "UIPassTemplate",
"PassClass": "RasterPass", "PassClass": "RasterPass",
"Slots": [ "Slots": [
{
"Name": "DepthInputOutput",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "DepthStencil",
"LoadStoreAction": {
"ClearValue": {
"Type": "DepthStencil",
"Value": [
0.0,
0.0,
0.0,
0.0
]
},
"LoadActionStencil": "Clear"
}
},
{ {
"Name": "InputOutput", "Name": "InputOutput",
"SlotType": "InputOutput", "SlotType": "InputOutput",

@ -10,6 +10,11 @@
{ {
"Name": "InputOutput", "Name": "InputOutput",
"SlotType": "InputOutput" "SlotType": "InputOutput"
},
{
"Name": "DepthInputOutput",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "DepthStencil"
} }
], ],
"PassRequests": [ "PassRequests": [
@ -24,6 +29,13 @@
"Pass": "Parent", "Pass": "Parent",
"Attachment": "InputOutput" "Attachment": "InputOutput"
} }
},
{
"LocalSlot": "DepthInputOutput",
"AttachmentRef": {
"Pass": "Parent",
"Attachment": "DepthInputOutput"
}
} }
], ],
"PassData": { "PassData": {

@ -138,6 +138,12 @@ namespace AZ
//! Without per draw viewport, the viewport setup in pass is usually used. //! Without per draw viewport, the viewport setup in pass is usually used.
void UnsetViewport(); void UnsetViewport();
//! Set stencil reference for following draws which are added to this DynamicDrawContext
void SetStencilReference(uint8_t stencilRef);
//! Get the current stencil reference.
uint8_t GetStencilReference() const;
//! Draw Indexed primitives with vertex and index data and per draw srg //! Draw Indexed primitives with vertex and index data and per draw srg
//! The per draw srg need to be provided if it's required by shader. //! The per draw srg need to be provided if it's required by shader.
void DrawIndexed(void* vertexData, uint32_t vertexCount, void* indexData, uint32_t indexCount, RHI::IndexFormat indexFormat, Data::Instance < ShaderResourceGroup> drawSrg = nullptr); void DrawIndexed(void* vertexData, uint32_t vertexCount, void* indexData, uint32_t indexCount, RHI::IndexFormat indexFormat, Data::Instance < ShaderResourceGroup> drawSrg = nullptr);
@ -204,10 +210,13 @@ namespace AZ
bool m_useScissor = false; bool m_useScissor = false;
RHI::Scissor m_scissor; RHI::Scissor m_scissor;
// current scissor // current viewport
bool m_useViewport = false; bool m_useViewport = false;
RHI::Viewport m_viewport; RHI::Viewport m_viewport;
// Current stencil reference value
uint8_t m_stencilRef = 0;
// Cached RHI pipeline states for different combination of render states // Cached RHI pipeline states for different combination of render states
AZStd::unordered_map<HashValue64, const RHI::PipelineState*> m_cachedRhiPipelineStates; AZStd::unordered_map<HashValue64, const RHI::PipelineState*> m_cachedRhiPipelineStates;

@ -382,6 +382,16 @@ namespace AZ
m_useViewport = false; m_useViewport = false;
} }
void DynamicDrawContext::SetStencilReference(uint8_t stencilRef)
{
m_stencilRef = stencilRef;
}
uint8_t DynamicDrawContext::GetStencilReference() const
{
return m_stencilRef;
}
void DynamicDrawContext::SetShaderVariant(ShaderVariantId shaderVariantId) void DynamicDrawContext::SetShaderVariant(ShaderVariantId shaderVariantId)
{ {
AZ_Assert( m_initialized && m_supportShaderVariants, "DynamicDrawContext is not initialized or unable to support shader variants. " AZ_Assert( m_initialized && m_supportShaderVariants, "DynamicDrawContext is not initialized or unable to support shader variants. "
@ -475,6 +485,9 @@ namespace AZ
drawItem.m_viewports = &m_viewport; drawItem.m_viewports = &m_viewport;
} }
// Set stencil reference. Used when stencil is enabled.
drawItem.m_stencilRef = m_stencilRef;
drawItemInfo.m_sortKey = m_sortKey++; drawItemInfo.m_sortKey = m_sortKey++;
m_cachedDrawItems.emplace_back(drawItemInfo); m_cachedDrawItems.emplace_back(drawItemInfo);
} }

@ -4,7 +4,7 @@
{ {
"StableId": 1, "StableId": 1,
"Options": { "Options": {
"o_preMultiplyAlpha": "true", "o_preMultiplyAlpha": "false",
"o_alphaTest": "false", "o_alphaTest": "false",
"o_srgbWrite": "true", "o_srgbWrite": "true",
"o_modulate": "Modulate::None" "o_modulate": "Modulate::None"
@ -14,7 +14,7 @@
"StableId": 2, "StableId": 2,
"Options": { "Options": {
"o_preMultiplyAlpha": "false", "o_preMultiplyAlpha": "false",
"o_alphaTest": "false", "o_alphaTest": "true",
"o_srgbWrite": "true", "o_srgbWrite": "true",
"o_modulate": "Modulate::None" "o_modulate": "Modulate::None"
} }

@ -137,7 +137,11 @@ namespace LyShine
AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw = uiRenderer->GetDynamicDrawContext(); AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw = uiRenderer->GetDynamicDrawContext();
const UiRenderer::UiShaderData& uiShaderData = uiRenderer->GetUiShaderData(); const UiRenderer::UiShaderData& uiShaderData = uiRenderer->GetUiShaderData();
dynamicDraw->SetShaderVariant(uiShaderData.m_shaderVariantDefault); // Set render state
dynamicDraw->SetStencilState(uiRenderer->GetBaseState().m_stencilState);
dynamicDraw->SetTarget0BlendState(uiRenderer->GetBaseState().m_blendState);
dynamicDraw->SetShaderVariant(uiRenderer->GetCurrentShaderVariant());
// Set up per draw SRG // Set up per draw SRG
AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> drawSrg = dynamicDraw->NewDrawSrg(); AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> drawSrg = dynamicDraw->NewDrawSrg();
@ -307,7 +311,7 @@ namespace LyShine
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void MaskRenderNode::Render(UiRenderer* uiRenderer) void MaskRenderNode::Render(UiRenderer* uiRenderer)
{ {
int priorBaseState = uiRenderer->GetBaseState(); UiRenderer::BaseState priorBaseState = uiRenderer->GetBaseState();
if (m_isMaskingEnabled || m_drawBehind) if (m_isMaskingEnabled || m_drawBehind)
{ {
@ -369,68 +373,61 @@ namespace LyShine
#endif #endif
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void MaskRenderNode::SetupBeforeRenderingMask(UiRenderer* uiRenderer, bool firstPass, int priorBaseState) void MaskRenderNode::SetupBeforeRenderingMask(UiRenderer* uiRenderer, bool firstPass, UiRenderer::BaseState priorBaseState)
{ {
UiRenderer::BaseState curBaseState = priorBaseState;
// If using alpha test for drawing the renderable components on this element then we turn on // If using alpha test for drawing the renderable components on this element then we turn on
// alpha test as a pre-render step // alpha test as a pre-render step
int alphaTest = 0; curBaseState.m_useAlphaTest = m_useAlphaTest;
if (m_useAlphaTest)
{
alphaTest = GS_ALPHATEST_GREATER;
}
// if either of the draw flags are checked then we may want to draw the renderable component(s) // if either of the draw flags are checked then we may want to draw the renderable component(s)
// on this element, otherwise use the color mask to stop them rendering // on this element, otherwise use the color mask to stop them rendering
int colorMask = GS_COLMASK_NONE; curBaseState.m_blendState.m_enable = false;
curBaseState.m_blendState.m_writeMask = 0x0;
if ((m_drawBehind && firstPass) || if ((m_drawBehind && firstPass) ||
(m_drawInFront && !firstPass)) (m_drawInFront && !firstPass))
{ {
colorMask = 0; // mask everything, don't write color or alpha, we just write to stencil buffer curBaseState.m_blendState.m_enable = true;
curBaseState.m_blendState.m_writeMask = 0xF;
} }
if (m_isMaskingEnabled) if (m_isMaskingEnabled)
{ {
AZ::RHI::StencilOpState stencilOpState;
stencilOpState.m_func = AZ::RHI::ComparisonFunc::Equal;
// masking is enabled so we want to setup to increment (first pass) or decrement (second pass) // masking is enabled so we want to setup to increment (first pass) or decrement (second pass)
// the stencil buff when rendering the renderable component(s) on this element // the stencil buff when rendering the renderable component(s) on this element
int passOp = 0;
if (firstPass) if (firstPass)
{ {
passOp = STENCOP_PASS(FSS_STENCOP_INCR); stencilOpState.m_passOp = AZ::RHI::StencilOp::Increment;
gEnv->pRenderer->PushProfileMarker(s_maskIncrProfileMarker);
} }
else else
{ {
passOp = STENCOP_PASS(FSS_STENCOP_DECR); stencilOpState.m_passOp = AZ::RHI::StencilOp::Decrement;
gEnv->pRenderer->PushProfileMarker(s_maskDecrProfileMarker);
} }
curBaseState.m_stencilState.m_frontFace = stencilOpState;
curBaseState.m_stencilState.m_backFace = stencilOpState;
// set up for stencil write // set up for stencil write
const uint32 stencilRef = uiRenderer->GetStencilRef(); AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw = uiRenderer->GetDynamicDrawContext();
const uint32 stencilMask = 0xFF; dynamicDraw->SetStencilReference(uiRenderer->GetStencilRef());
const uint32 stencilWriteMask = 0xFF; curBaseState.m_stencilState.m_enable = true;
const int32 stencilState = STENC_FUNC(FSS_STENCFUNC_EQUAL) curBaseState.m_stencilState.m_writeMask = 0xFF;
| STENCOP_FAIL(FSS_STENCOP_KEEP) | STENCOP_ZFAIL(FSS_STENCOP_KEEP) | passOp;
gEnv->pRenderer->SetStencilState(stencilState, stencilRef, stencilMask, stencilWriteMask);
// Set the base state that should be used when rendering the renderable component(s) on this
// element
uiRenderer->SetBaseState(priorBaseState | GS_STENCIL | alphaTest | colorMask);
} }
else else
{ {
// masking is not enabled // masking is not enabled
curBaseState.m_stencilState.m_enable = false;
// Even if not masking we still use alpha test (if checked). This is primarily to help the user to
// visualize what their alpha tested mask looks like.
if (colorMask || alphaTest)
{
uiRenderer->SetBaseState(priorBaseState | colorMask | alphaTest);
}
} }
uiRenderer->SetBaseState(curBaseState);
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void MaskRenderNode::SetupAfterRenderingMask(UiRenderer* uiRenderer, bool firstPass, int priorBaseState) void MaskRenderNode::SetupAfterRenderingMask(UiRenderer* uiRenderer, bool firstPass, UiRenderer::BaseState priorBaseState)
{ {
if (m_isMaskingEnabled) if (m_isMaskingEnabled)
{ {
@ -442,26 +439,29 @@ namespace LyShine
if (firstPass) if (firstPass)
{ {
uiRenderer->IncrementStencilRef(); uiRenderer->IncrementStencilRef();
gEnv->pRenderer->PopProfileMarker(s_maskIncrProfileMarker);
} }
else else
{ {
uiRenderer->DecrementStencilRef(); uiRenderer->DecrementStencilRef();
gEnv->pRenderer->PopProfileMarker(s_maskDecrProfileMarker);
} }
// turn off stencil write and turn on stencil test AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw = uiRenderer->GetDynamicDrawContext();
const uint32 stencilRef = uiRenderer->GetStencilRef(); dynamicDraw->SetStencilReference(uiRenderer->GetStencilRef());
const uint32 stencilMask = 0xFF;
const uint32 stencilWriteMask = 0x00;
const int32 stencilState = STENC_FUNC(FSS_STENCFUNC_EQUAL)
| STENCOP_FAIL(FSS_STENCOP_KEEP) | STENCOP_ZFAIL(FSS_STENCOP_KEEP) | STENCOP_PASS(FSS_STENCOP_KEEP);
gEnv->pRenderer->SetStencilState(stencilState, stencilRef, stencilMask, stencilWriteMask);
if (firstPass) if (firstPass)
{ {
// first pass, turn on stencil test for drawing children UiRenderer::BaseState curBaseState = priorBaseState;
uiRenderer->SetBaseState(priorBaseState | GS_STENCIL);
// turn off stencil write and turn on stencil test
curBaseState.m_stencilState.m_enable = true;
curBaseState.m_stencilState.m_writeMask = 0x00;
AZ::RHI::StencilOpState stencilOpState;
stencilOpState.m_func = AZ::RHI::ComparisonFunc::Equal;
curBaseState.m_stencilState.m_frontFace = stencilOpState;
curBaseState.m_stencilState.m_backFace = stencilOpState;
uiRenderer->SetBaseState(curBaseState);
} }
else else
{ {
@ -475,7 +475,6 @@ namespace LyShine
// remove any color mask or alpha test that we set in pre-render // remove any color mask or alpha test that we set in pre-render
uiRenderer->SetBaseState(priorBaseState); uiRenderer->SetBaseState(priorBaseState);
} }
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -637,35 +636,24 @@ namespace LyShine
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void RenderGraph::BeginMask(bool isMaskingEnabled, bool useAlphaTest, bool drawBehind, bool drawInFront) void RenderGraph::BeginMask(bool isMaskingEnabled, bool useAlphaTest, bool drawBehind, bool drawInFront)
{ {
#ifdef LYSHINE_ATOM_TODO // keeping this code for future phase (masks and render targets)
// this uses pool allocator // this uses pool allocator
MaskRenderNode* maskRenderNode = new MaskRenderNode(m_currentMask, isMaskingEnabled, useAlphaTest, drawBehind, drawInFront); MaskRenderNode* maskRenderNode = new MaskRenderNode(m_currentMask, isMaskingEnabled, useAlphaTest, drawBehind, drawInFront);
m_currentMask = maskRenderNode; m_currentMask = maskRenderNode;
m_renderNodeListStack.push(&maskRenderNode->GetMaskRenderNodeList()); m_renderNodeListStack.push(&maskRenderNode->GetMaskRenderNodeList());
#else
AZ_UNUSED(drawInFront);
AZ_UNUSED(drawBehind);
AZ_UNUSED(useAlphaTest);
AZ_UNUSED(isMaskingEnabled);
#endif
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void RenderGraph::StartChildrenForMask() void RenderGraph::StartChildrenForMask()
{ {
#ifdef LYSHINE_ATOM_TODO // keeping this code for future phase (masks and render targets)
AZ_Assert(m_currentMask, "Calling StartChildrenForMask while not defining a mask"); AZ_Assert(m_currentMask, "Calling StartChildrenForMask while not defining a mask");
m_renderNodeListStack.pop(); m_renderNodeListStack.pop();
m_renderNodeListStack.push(&m_currentMask->GetContentRenderNodeList()); m_renderNodeListStack.push(&m_currentMask->GetContentRenderNodeList());
#endif
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void RenderGraph::EndMask() void RenderGraph::EndMask()
{ {
#ifdef LYSHINE_ATOM_TODO // keeping this code for future phase (masks and render targets)
AZ_Assert(m_currentMask, "Calling EndMask while not defining a mask"); AZ_Assert(m_currentMask, "Calling EndMask while not defining a mask");
if (m_currentMask) if (m_currentMask)
{ {
@ -686,7 +674,6 @@ namespace LyShine
m_renderNodeListStack.top()->push_back(newMaskRenderNode); m_renderNodeListStack.top()->push_back(newMaskRenderNode);
} }
} }
#endif
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -996,6 +983,12 @@ namespace LyShine
// LYSHINE_ATOM_TODO - will probably need to support this when converting UI Editor to use Atom // LYSHINE_ATOM_TODO - will probably need to support this when converting UI Editor to use Atom
AZ_UNUSED(viewportSize); AZ_UNUSED(viewportSize);
AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw = uiRenderer->GetDynamicDrawContext();
// Disable stencil and enable blend/color write
dynamicDraw->SetStencilState(uiRenderer->GetBaseState().m_stencilState);
dynamicDraw->SetTarget0BlendState(uiRenderer->GetBaseState().m_blendState);
// First render the render targets, they are sorted so that more deeply nested ones are rendered first. // First render the render targets, they are sorted so that more deeply nested ones are rendered first.
#ifdef LYSHINE_ATOM_TODO // keeping this code for reference for future phase (render targets) #ifdef LYSHINE_ATOM_TODO // keeping this code for reference for future phase (render targets)

@ -22,12 +22,11 @@
#include <Atom/RPI.Reflect/Image/Image.h> #include <Atom/RPI.Reflect/Image/Image.h>
#include <AtomCore/Instance/Instance.h> #include <AtomCore/Instance/Instance.h>
#include "UiRenderer.h"
#ifndef _RELEASE #ifndef _RELEASE
#include "LyShineDebug.h" #include "LyShineDebug.h"
#endif #endif
class UiRenderer;
namespace LyShine namespace LyShine
{ {
enum RenderNodeType enum RenderNodeType
@ -157,8 +156,8 @@ namespace LyShine
#endif #endif
private: // functions private: // functions
void SetupBeforeRenderingMask(UiRenderer* uiRenderer, bool firstPass, int priorBaseState); void SetupBeforeRenderingMask(UiRenderer* uiRenderer, bool firstPass, UiRenderer::BaseState priorBaseState);
void SetupAfterRenderingMask(UiRenderer* uiRenderer, bool firstPass, int priorBaseState); void SetupAfterRenderingMask(UiRenderer* uiRenderer, bool firstPass, UiRenderer::BaseState priorBaseState);
private: // data private: // data
AZStd::vector<RenderNode*> m_maskRenderNodes; //!< The render nodes used to render the mask shape AZStd::vector<RenderNode*> m_maskRenderNodes; //!< The render nodes used to render the mask shape

@ -20,7 +20,6 @@
#include <Atom/Bootstrap/DefaultWindowBus.h> #include <Atom/Bootstrap/DefaultWindowBus.h>
#include <Atom/RPI.Public/ViewportContextBus.h> #include <Atom/RPI.Public/ViewportContextBus.h>
#include <Atom/RPI.Public/RenderPipeline.h> #include <Atom/RPI.Public/RenderPipeline.h>
#include <IRenderer.h> // LYSHINE_ATOM_TODO - remove when GS_DEPTHFUNC_LEQUAL reference is removed with LyShine render target Atom conversion
#include <AzCore/Math/MatrixUtils.h> #include <AzCore/Math/MatrixUtils.h>
#include <AzCore/Debug/Trace.h> #include <AzCore/Debug/Trace.h>
@ -33,9 +32,7 @@
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
UiRenderer::UiRenderer(AZ::RPI::ViewportContextPtr viewportContext) UiRenderer::UiRenderer(AZ::RPI::ViewportContextPtr viewportContext)
: m_baseState(GS_DEPTHFUNC_LEQUAL) : m_viewportContext(viewportContext)
, m_stencilRef(0)
, m_viewportContext(viewportContext)
{ {
// Use bootstrap scene event to indicate when the RPI has fully // Use bootstrap scene event to indicate when the RPI has fully
// initialized with all assets loaded and is ready to be used // initialized with all assets loaded and is ready to be used
@ -127,6 +124,8 @@ void UiRenderer::CreateDynamicDrawContext(AZ::RPI::ScenePtr scene, AZ::Data::Ins
{ "TEXCOORD", AZ::RHI::Format::R32G32_FLOAT }, { "TEXCOORD", AZ::RHI::Format::R32G32_FLOAT },
{ "BLENDINDICES", AZ::RHI::Format::R16G16_UINT } } { "BLENDINDICES", AZ::RHI::Format::R16G16_UINT } }
); );
m_dynamicDraw->AddDrawStateOptions(AZ::RPI::DynamicDrawContext::DrawStateOptions::StencilState
| AZ::RPI::DynamicDrawContext::DrawStateOptions::BlendMode);
m_dynamicDraw->EndInit(); m_dynamicDraw->EndInit();
} }
@ -170,25 +169,24 @@ void UiRenderer::CacheShaderData(const AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext>
shaderOptionsDefault.push_back(AZ::RPI::ShaderOption(AZ::Name("o_srgbWrite"), AZ::Name("true"))); shaderOptionsDefault.push_back(AZ::RPI::ShaderOption(AZ::Name("o_srgbWrite"), AZ::Name("true")));
shaderOptionsDefault.push_back(AZ::RPI::ShaderOption(AZ::Name("o_modulate"), AZ::Name("Modulate::None"))); shaderOptionsDefault.push_back(AZ::RPI::ShaderOption(AZ::Name("o_modulate"), AZ::Name("Modulate::None")));
m_uiShaderData.m_shaderVariantDefault = dynamicDraw->UseShaderVariant(shaderOptionsDefault); m_uiShaderData.m_shaderVariantDefault = dynamicDraw->UseShaderVariant(shaderOptionsDefault);
AZ::RPI::ShaderOptionList shaderOptionsAlphaTest;
shaderOptionsAlphaTest.push_back(AZ::RPI::ShaderOption(AZ::Name("o_preMultiplyAlpha"), AZ::Name("false")));
shaderOptionsAlphaTest.push_back(AZ::RPI::ShaderOption(AZ::Name("o_alphaTest"), AZ::Name("true")));
shaderOptionsAlphaTest.push_back(AZ::RPI::ShaderOption(AZ::Name("o_srgbWrite"), AZ::Name("true")));
shaderOptionsAlphaTest.push_back(AZ::RPI::ShaderOption(AZ::Name("o_modulate"), AZ::Name("Modulate::None")));
m_uiShaderData.m_shaderVariantAlphaTest = dynamicDraw->UseShaderVariant(shaderOptionsAlphaTest);
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void UiRenderer::BeginUiFrameRender() void UiRenderer::BeginUiFrameRender()
{ {
#ifdef LYSHINE_ATOM_TODO
m_renderer = gEnv->pRenderer;
// we are rendering at the end of the frame, after tone mapping, so we should be writing sRGB values
m_renderer->SetSrgbWrite(true);
#ifndef _RELEASE #ifndef _RELEASE
if (m_debugTextureDataRecordLevel > 0) if (m_debugTextureDataRecordLevel > 0)
{ {
m_texturesUsedInFrame.clear(); m_texturesUsedInFrame.clear();
} }
#endif #endif
#endif
// Various platform drivers expect all texture slots used in the shader to be bound // Various platform drivers expect all texture slots used in the shader to be bound
BindNullTexture(); BindNullTexture();
} }
@ -204,18 +202,10 @@ void UiRenderer::EndUiFrameRender()
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void UiRenderer::BeginCanvasRender() void UiRenderer::BeginCanvasRender()
{ {
#ifdef LYSHINE_ATOM_TODO
m_baseState = GS_NODEPTHTEST;
m_stencilRef = 0; m_stencilRef = 0;
// Set default starting state // Set base state
IRenderer* renderer = gEnv->pRenderer; m_baseState.ResetToDefault();
renderer->SetCullMode(R_CULL_DISABLE);
renderer->SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
renderer->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST);
#endif
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -229,11 +219,13 @@ AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> UiRenderer::GetDynamicDrawContext()
return m_dynamicDraw; return m_dynamicDraw;
} }
////////////////////////////////////////////////////////////////////////////////////////////////////
const UiRenderer::UiShaderData& UiRenderer::GetUiShaderData() const UiRenderer::UiShaderData& UiRenderer::GetUiShaderData()
{ {
return m_uiShaderData; return m_uiShaderData;
} }
////////////////////////////////////////////////////////////////////////////////////////////////////
AZ::Matrix4x4 UiRenderer::GetModelViewProjectionMatrix() AZ::Matrix4x4 UiRenderer::GetModelViewProjectionMatrix()
{ {
auto viewportContext = GetViewportContext(); auto viewportContext = GetViewportContext();
@ -253,6 +245,7 @@ AZ::Matrix4x4 UiRenderer::GetModelViewProjectionMatrix()
return modelViewProjMat; return modelViewProjMat;
} }
////////////////////////////////////////////////////////////////////////////////////////////////////
AZ::Vector2 UiRenderer::GetViewportSize() AZ::Vector2 UiRenderer::GetViewportSize()
{ {
auto viewportContext = GetViewportContext(); auto viewportContext = GetViewportContext();
@ -267,17 +260,30 @@ AZ::Vector2 UiRenderer::GetViewportSize()
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
int UiRenderer::GetBaseState() UiRenderer::BaseState UiRenderer::GetBaseState()
{ {
return m_baseState; return m_baseState;
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void UiRenderer::SetBaseState(int state) void UiRenderer::SetBaseState(BaseState state)
{ {
m_baseState = state; m_baseState = state;
} }
////////////////////////////////////////////////////////////////////////////////////////////////////
AZ::RPI::ShaderVariantId UiRenderer::GetCurrentShaderVariant()
{
AZ::RPI::ShaderVariantId variantId = m_uiShaderData.m_shaderVariantDefault;
if (m_baseState.m_useAlphaTest)
{
variantId = m_uiShaderData.m_shaderVariantAlphaTest;
}
return variantId;
}
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
uint32 UiRenderer::GetStencilRef() uint32 UiRenderer::GetStencilRef()
{ {
@ -354,6 +360,7 @@ void UiRenderer::DebugDisplayTextureData(int recordingOption)
{ {
if (recordingOption > 0) if (recordingOption > 0)
{ {
#ifdef LYSHINE_ATOM_TODO // Convert debug to use Atom images
// compute the total area of all the textures, also create a vector that we can sort by area // compute the total area of all the textures, also create a vector that we can sort by area
AZStd::vector<ITexture*> textures; AZStd::vector<ITexture*> textures;
int totalArea = 0; int totalArea = 0;
@ -431,6 +438,7 @@ void UiRenderer::DebugDisplayTextureData(int recordingOption)
texture->GetWidth(), texture->GetHeight(), texture->GetDataSize(), texture->GetFormatName(), texture->GetName()); texture->GetWidth(), texture->GetHeight(), texture->GetDataSize(), texture->GetFormatName(), texture->GetName());
WriteLine(buffer, white); WriteLine(buffer, white);
} }
#endif
} }
} }

@ -14,6 +14,7 @@
#include <Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h> #include <Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h>
#include <Atom/RPI.Public/WindowContext.h> #include <Atom/RPI.Public/WindowContext.h>
#include <Atom/RPI.Public/ViewportContext.h> #include <Atom/RPI.Public/ViewportContext.h>
#include <Atom/RHI.Reflect/RenderStates.h>
#include <Atom/Bootstrap/BootstrapNotificationBus.h> #include <Atom/Bootstrap/BootstrapNotificationBus.h>
#ifndef _RELEASE #ifndef _RELEASE
@ -38,6 +39,36 @@ public: // types
AZ::RHI::ShaderInputConstantIndex m_isClampInputIndex; AZ::RHI::ShaderInputConstantIndex m_isClampInputIndex;
AZ::RPI::ShaderVariantId m_shaderVariantDefault; AZ::RPI::ShaderVariantId m_shaderVariantDefault;
AZ::RPI::ShaderVariantId m_shaderVariantAlphaTest;
};
// Base state
struct BaseState
{
BaseState()
{
ResetToDefault();
}
void ResetToDefault()
{
// Enable blend/color write
m_blendState.m_enable = true;
m_blendState.m_writeMask = 0xF;
m_blendState.m_blendSource = AZ::RHI::BlendFactor::AlphaSource;
m_blendState.m_blendDest = AZ::RHI::BlendFactor::AlphaSourceInverse;
m_blendState.m_blendOp = AZ::RHI::BlendOp::Add;
// Disable stencil
m_stencilState = AZ::RHI::StencilState();
m_stencilState.m_enable = 0;
m_useAlphaTest = false;
}
AZ::RHI::TargetBlendState m_blendState;
AZ::RHI::StencilState m_stencilState;
bool m_useAlphaTest = false;
}; };
public: // member functions public: // member functions
@ -74,10 +105,13 @@ public: // member functions
AZ::Vector2 GetViewportSize(); AZ::Vector2 GetViewportSize();
//! Get the current base state //! Get the current base state
int GetBaseState(); BaseState GetBaseState();
//! Set the base state //! Set the base state
void SetBaseState(int state); void SetBaseState(BaseState state);
//! Get the shader variant based on current render properties
AZ::RPI::ShaderVariantId GetCurrentShaderVariant();
//! Get the current stencil test reference value //! Get the current stencil test reference value
uint32 GetStencilRef(); uint32 GetStencilRef();
@ -126,8 +160,8 @@ protected: // attributes
static constexpr char LogName[] = "UiRenderer"; static constexpr char LogName[] = "UiRenderer";
int m_baseState; BaseState m_baseState;
uint32 m_stencilRef; uint32 m_stencilRef = 0;
UiShaderData m_uiShaderData; UiShaderData m_uiShaderData;
AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> m_dynamicDraw; AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> m_dynamicDraw;

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8474b897fe02f70ed8d0e5c47cae8c816c832a7a5739b8c32317737fd275774f
size 1069752
Loading…
Cancel
Save