Fix up particle emitter to work with Atom (#626)

* Fix up particle emitter component to work with Atom

* PR feedback and disable render target tests until supported
This commit is contained in:
michabr
2021-05-07 11:25:57 -07:00
committed by abrmich
parent 3219c787ac
commit d9cb61575e
8 changed files with 76 additions and 111 deletions
@@ -16,9 +16,6 @@
#include <LyShine/Bus/UiTransformBus.h>
#include <AzCore/Math/Vector2.h>
// forward declarations
class ITexture;
////////////////////////////////////////////////////////////////////////////////////////////////////
//! A sprite is a texture with extra information about how it behaves for 2D drawing
//! Currently a sprite exists on disk as a side car file next to the texture file.
@@ -80,9 +77,6 @@ public: // member functions
//! Set the borders of a given cell within the sprite-sheet.
virtual void SetCellBorders(int cellIndex, Borders borders) = 0;
//! Get the texture for this sprite
virtual ITexture* GetTexture() = 0;
//! Serialize this object for save/load
virtual void Serialize(TSerialize ser) = 0;
+12 -72
View File
@@ -11,7 +11,6 @@
*/
#include "LyShine_precompiled.h"
#include "Sprite.h"
#include <ITexture.h>
#include <CryPath.h>
#include <IRenderer.h>
#include <ISerialize.h>
@@ -193,8 +192,7 @@ AZStd::string CSprite::s_emptyString;
////////////////////////////////////////////////////////////////////////////////////////////////////
CSprite::CSprite()
: m_texture(nullptr)
, m_numSpriteSheetCellTags(0)
: m_numSpriteSheetCellTags(0)
, m_atlas(nullptr)
{
AddRef();
@@ -204,8 +202,6 @@ CSprite::CSprite()
////////////////////////////////////////////////////////////////////////////////////////////////////
CSprite::~CSprite()
{
ReleaseTexture(m_texture);
s_loadedSprites->erase(m_pathname);
TextureAtlasNamespace::TextureAtlasNotificationBus::Handler::BusDisconnect();
}
@@ -250,26 +246,17 @@ void CSprite::SetCellBorders(int cellIndex, Borders borders)
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ITexture* CSprite::GetTexture()
AZ::Data::Instance<AZ::RPI::Image> CSprite::GetImage()
{
// Prioritize usage of an atlas
#ifdef LYSHINE_ATOM_TODO // texture atlas conversion to use Atom
if (m_atlas)
{
return m_atlas->GetTexture();
}
#endif
if (!m_texture && !m_pathname.empty())
{
// the render target texture may not have existed when the sprite was created
m_texture = gEnv->pRenderer->EF_GetTextureByName(m_pathname.c_str());
if (m_texture)
{
// increase the reference count to this texture so it doesn't get removed while
// we are using it
m_texture->AddRef();
}
}
return m_texture;
return m_image;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -377,31 +364,21 @@ bool CSprite::AreCellBordersZeroWidth(int cellIndex) const
////////////////////////////////////////////////////////////////////////////////////////////////////
AZ::Vector2 CSprite::GetSize()
{
#ifdef LYSHINE_ATOM_TODO // Convert texture atlases to use Atom
ITexture* texture = GetTexture();
if (texture)
AZ::Data::Instance<AZ::RPI::Image> image = GetImage();
if (image)
{
if (m_atlas)
{
return AZ::Vector2(static_cast<float>(m_atlasCoordinates.GetWidth()), static_cast<float>(m_atlasCoordinates.GetHeight()));
}
return AZ::Vector2(static_cast<float>(texture->GetWidth()), static_cast<float>(texture->GetHeight()));
}
else
{
return AZ::Vector2(0.0f, 0.0f);
}
#else
if (m_image)
{
AZ::RHI::Size size = m_image->GetRHIImage()->GetDescriptor().m_size;
AZ::RHI::Size size = image->GetRHIImage()->GetDescriptor().m_size;
return AZ::Vector2(size.m_width, size.m_height);
}
else
{
return AZ::Vector2(0.0f, 0.0f);
}
#endif
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -734,6 +711,7 @@ CSprite* CSprite::CreateSprite(const string& renderTargetName)
// create Sprite object
CSprite* sprite = new CSprite;
#ifdef LYSHINE_ATOM_TODO // render target converstion to use ATom
// the render target texture may not exist yet in which case we will need to load it later
sprite->m_texture = gEnv->pRenderer->EF_GetTextureByName(renderTargetName.c_str());
if (sprite->m_texture)
@@ -742,6 +720,7 @@ CSprite* CSprite::CreateSprite(const string& renderTargetName)
// while we are using it
sprite->m_texture->AddRef();
}
#endif
sprite->m_pathname = renderTargetName;
sprite->m_texturePathname.clear();
@@ -833,6 +812,7 @@ bool CSprite::FixUpSourceImagePathFromUserDefinedPath(const AZStd::string& userD
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
AZStd::string CSprite::GetImageSourcePathFromProductPath(const AZStd::string& productPathname)
{
AZStd::string sourcePathname(productPathname);
@@ -843,46 +823,6 @@ AZStd::string CSprite::GetImageSourcePathFromProductPath(const AZStd::string& pr
return sourcePathname;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool CSprite::LoadTexture(const string& texturePathname, const string& pathname, ITexture*& texture)
{
uint32 loadTextureFlags = (FT_USAGE_ALLOWREADSRGB | FT_DONT_STREAM);
texture = gEnv->pRenderer->EF_LoadTexture(texturePathname.c_str(), loadTextureFlags);
if (!texture || !texture->IsTextureLoaded())
{
gEnv->pSystem->Warning(
VALIDATOR_MODULE_SHINE,
VALIDATOR_WARNING,
VALIDATOR_FLAG_FILE | VALIDATOR_FLAG_TEXTURE,
texturePathname.c_str(),
"No texture file found for sprite: %s, no sprite will be used. "
"NOTE: File must be in current project or a gem.",
pathname.c_str());
texture = nullptr;
return false;
}
texture->SetFilter(FILTER_LINEAR);
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CSprite::ReleaseTexture(ITexture*& texture)
{
if (texture)
{
// In order to avoid the texture being deleted while there are still commands on the render
// thread command queue that use it, we queue a command to delete the texture onto the
// command queue.
auto pInfo = AZStd::make_unique<SResourceAsync>();
pInfo->eClassName = eRCN_Texture;
pInfo->pResource = texture;
gEnv->pRenderer->ReleaseResourceAsync(AZStd::move(pInfo));
texture = nullptr;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool CSprite::LoadImage(const AZStd::string& nameTex, AZ::Data::Instance<AZ::RPI::Image>& image)
{
+1 -6
View File
@@ -41,7 +41,6 @@ public: // member functions
Borders GetBorders() const override;
void SetBorders(Borders borders) override;
void SetCellBorders(int cellIndex, Borders borders) override;
ITexture* GetTexture() override;
void Serialize(TSerialize ser) override;
bool SaveToXml(const string& pathname) override;
bool AreBordersZeroWidth() const override;
@@ -71,7 +70,7 @@ public: // member functions
// ~TextureAtlasNotifications
AZ::Data::Instance<AZ::RPI::Image> GetImage() { return m_image; }
AZ::Data::Instance<AZ::RPI::Image> GetImage();
public: // static member functions
@@ -93,9 +92,6 @@ public: // static member functions
static AZStd::string GetImageSourcePathFromProductPath(const AZStd::string& productPathname);
private:
static bool LoadTexture(const string& texturePathname, const string& pathname, ITexture*& texture);
static void ReleaseTexture(ITexture*& texture);
static bool LoadImage(const AZStd::string& nameTex, AZ::Data::Instance<AZ::RPI::Image>& image);
static void ReleaseImage(AZ::Data::Instance<AZ::RPI::Image>& image);
@@ -120,7 +116,6 @@ private: // data
string m_pathname;
string m_texturePathname;
Borders m_borders;
ITexture* m_texture;
AZ::Data::Instance<AZ::RPI::Image> m_image;
int m_numSpriteSheetCellTags; //!< Number of Cell child-tags in sprite XML; unfortunately needed to help with serialization.
+21 -17
View File
@@ -34,9 +34,8 @@
#include <LyShine/IRenderGraph.h>
#include "UiSerialize.h"
#include "Sprite.h"
#include "UiLayoutHelpers.h"
#include "Sprite.h"
#include "RenderGraph.h"
namespace
@@ -281,6 +280,20 @@ namespace
14, 15, 21, 21, 20, 14, // center quad
};
AZ::Data::Instance<AZ::RPI::Image> GetSpriteImage(ISprite* sprite)
{
AZ::Data::Instance<AZ::RPI::Image> image;
if (sprite)
{
CSprite* cSprite = dynamic_cast<CSprite*>(sprite); // LYSHINE_ATOM_TODO - find a different solution from downcasting
if (cSprite)
{
image = cSprite->GetImage();
}
}
return image;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -471,20 +484,12 @@ void UiImageComponent::Render(LyShine::IRenderGraph* renderGraph)
renderGraph->AddPrimitive(&m_cachedPrimitive, texture, isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, m_blendMode);
#else
AZ::Data::Instance<AZ::RPI::Image> image;
if (sprite)
{
CSprite* cSprite = static_cast<CSprite*>(sprite); // LYSHINE_ATOM_TODO - find a different solution from downcasting
if (cSprite)
{
image = cSprite->GetImage();
}
}
AZ::Data::Instance<AZ::RPI::Image> image = GetSpriteImage(sprite);
bool isClampTextureMode = m_imageType == ImageType::Tiled ? false : true;
bool isTextureSRGB = IsSpriteTypeRenderTarget() && m_isRenderTargetSRGB;
bool isTexturePremultipliedAlpha = false; // we are not rendering from a render target with alpha in it
LyShine::RenderGraph* lyRenderGraph = static_cast<LyShine::RenderGraph*>(renderGraph); // LYSHINE_ATOM_TODO - find a different solution from downcasting
LyShine::RenderGraph* lyRenderGraph = dynamic_cast<LyShine::RenderGraph*>(renderGraph); // LYSHINE_ATOM_TODO - find a different solution from downcasting
if (lyRenderGraph)
{
lyRenderGraph->AddPrimitiveAtom(&m_cachedPrimitive, image, isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, m_blendMode);
@@ -880,8 +885,7 @@ float UiImageComponent::GetTargetWidth(float /*maxWidth*/)
{
float targetWidth = 0.0f;
ITexture* texture = (m_sprite) ? m_sprite->GetTexture() : nullptr;
if (texture)
if (m_sprite)
{
switch (m_imageType)
{
@@ -915,8 +919,7 @@ float UiImageComponent::GetTargetHeight(float /*maxHeight*/)
{
float targetHeight = 0.0f;
ITexture* texture = (m_sprite) ? m_sprite->GetTexture() : nullptr;
if (texture)
if (m_sprite)
{
switch (m_imageType)
{
@@ -2363,7 +2366,8 @@ void UiImageComponent::SnapOffsetsToFixedImage()
}
// if the image has no texture it will not use Fixed rendering so do nothing
if (!m_sprite || !m_sprite->GetTexture())
AZ::Data::Instance<AZ::RPI::Image> image = GetSpriteImage(m_sprite);
if (!image)
{
return;
}
@@ -12,6 +12,9 @@
#include "LyShine_precompiled.h"
#include "UiImageSequenceComponent.h"
#include "Sprite.h"
#include "RenderGraph.h"
#include <LyShine/Draw2d.h>
#include <LyShine/ISprite.h>
#include <LyShine/IRenderGraph.h>
@@ -100,7 +103,7 @@ void UiImageSequenceComponent::Render(LyShine::IRenderGraph* renderGraph)
return;
}
ISprite* sprite = m_spriteList[m_sequenceIndex];
CSprite* sprite = dynamic_cast<CSprite*>(m_spriteList[m_sequenceIndex]);
// get fade value (tracked by UiRenderer) and compute the desired alpha for the image
float fade = renderGraph->GetAlphaFade();
@@ -158,15 +161,23 @@ void UiImageSequenceComponent::Render(LyShine::IRenderGraph* renderGraph)
}
}
ITexture* texture = (sprite) ? sprite->GetTexture() : nullptr;
AZ::Data::Instance<AZ::RPI::Image> image;
if (sprite)
{
image = sprite->GetImage();
}
bool isClampTextureMode = false;
bool isTextureSRGB = false;
bool isTexturePremultipliedAlpha = false;
LyShine::BlendMode blendMode = LyShine::BlendMode::Normal;
// Add the quad to the render graph
renderGraph->AddPrimitive(&m_cachedPrimitive, texture,
isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, blendMode);
LyShine::RenderGraph* lyRenderGraph = dynamic_cast<LyShine::RenderGraph*>(renderGraph);
if (lyRenderGraph)
{
lyRenderGraph->AddPrimitiveAtom(&m_cachedPrimitive, image,
isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, blendMode);
}
}
}
@@ -13,6 +13,8 @@
#include "UiParticleEmitterComponent.h"
#include "EditorPropertyTypes.h"
#include "Sprite.h"
#include "RenderGraph.h"
#include <AzCore/Math/Crc.h>
#include <AzCore/RTTI/BehaviorContext.h>
@@ -21,7 +23,6 @@
#include <AzCore/std/sort.h>
#include <LyShine/ISprite.h>
#include <IRenderer.h>
#include <LyShine/IDraw2d.h>
#include <LyShine/ISprite.h>
@@ -764,6 +765,12 @@ void UiParticleEmitterComponent::InGamePostActivate()
////////////////////////////////////////////////////////////////////////////////////////////////////
void UiParticleEmitterComponent::Render(LyShine::IRenderGraph* renderGraph)
{
AZ::u32 particlesToRender = AZ::GetMin<AZ::u32>(m_particleContainer.size(), m_particleBufferSize);
if (particlesToRender == 0)
{
return;
}
AZ::Matrix4x4 transform = AZ::Matrix4x4::CreateIdentity();
AZ::Vector2 emitterOffset = AZ::Vector2::CreateZero();
@@ -781,9 +788,15 @@ void UiParticleEmitterComponent::Render(LyShine::IRenderGraph* renderGraph)
EBUS_EVENT_ID_RESULT(transform, canvasID, UiCanvasBus, GetCanvasToViewportMatrix);
}
AZ::u32 particlesToRender = AZ::GetMin<AZ::u32>(m_particleContainer.size(), m_particleBufferSize);
ITexture* texture = (m_sprite) ? m_sprite->GetTexture() : nullptr;
AZ::Data::Instance<AZ::RPI::Image> image;
if (m_sprite)
{
CSprite* sprite = dynamic_cast<CSprite*>(m_sprite);
if (sprite)
{
image = sprite->GetImage();
}
}
bool isClampTextureMode = true;
bool isTextureSRGB = false;
@@ -836,7 +849,11 @@ void UiParticleEmitterComponent::Render(LyShine::IRenderGraph* renderGraph)
m_cachedPrimitive.m_numVertices = totalVerticesInserted;
m_cachedPrimitive.m_numIndices = totalParticlesInserted * indicesPerParticle;
renderGraph->AddPrimitive(&m_cachedPrimitive, texture, isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, m_blendMode);
LyShine::RenderGraph* lyRenderGraph = dynamic_cast<LyShine::RenderGraph*>(renderGraph);
if (lyRenderGraph)
{
lyRenderGraph->AddPrimitiveAtom(&m_cachedPrimitive, image, isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, m_blendMode);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
+2
View File
@@ -68,6 +68,7 @@ namespace UnitTest
AZStd::unique_ptr<DataMembers> m_data;
};
#ifdef LYSHINE_ATOM_TODO // [LYN-3359] - render target support using Atom
TEST_F(LyShineSpriteTest, Sprite_CanAcquireRenderTarget)
{
// initialize to create the static sprite cache
@@ -130,6 +131,7 @@ namespace UnitTest
CSprite::Shutdown();
delete mockTexture;
}
#endif
} //namespace UnitTest
AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV);
@@ -78,8 +78,9 @@ namespace LyShineExamples
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void UiCustomImageComponent::Render(LyShine::IRenderGraph* renderGraph)
void UiCustomImageComponent::Render([[maybe_unused]] LyShine::IRenderGraph* renderGraph)
{
#ifdef LYSHINE_ATOM_TODO // [LYN-3635] convert to use Atom
// get fade value (tracked by UiRenderer) and compute the desired alpha for the image
float fade = renderGraph->GetAlphaFade();
float desiredAlpha = m_overrideAlpha * fade;
@@ -126,6 +127,7 @@ namespace LyShineExamples
bool isTexturePremultipliedAlpha = false; // we are not rendering from a render target with alpha in it
LyShine::BlendMode blendMode = LyShine::BlendMode::Normal;
renderGraph->AddPrimitive(&m_cachedPrimitive, texture, m_clamp, isTextureSRGB, isTexturePremultipliedAlpha, blendMode);
#endif
}
////////////////////////////////////////////////////////////////////////////////////////////////////