#ifndef __EFFEKSEERRENDERER_SPRITE_RENDERER_BASE_H__ #define __EFFEKSEERRENDERER_SPRITE_RENDERER_BASE_H__ //---------------------------------------------------------------------------------- // Include //---------------------------------------------------------------------------------- #include #include #include #include #include #include "EffekseerRenderer.CommonUtils.h" #include "EffekseerRenderer.IndexBufferBase.h" #include "EffekseerRenderer.RenderStateBase.h" #include "EffekseerRenderer.StandardRenderer.h" #include "EffekseerRenderer.VertexBufferBase.h" //----------------------------------------------------------------------------------- // //----------------------------------------------------------------------------------- namespace EffekseerRenderer { //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- typedef ::Effekseer::SpriteRenderer::NodeParameter efkSpriteNodeParam; typedef ::Effekseer::SpriteRenderer::InstanceParameter efkSpriteInstanceParam; typedef ::Effekseer::SIMD::Vec3f efkVector3D; template class SpriteRendererBase : public ::Effekseer::SpriteRenderer, public ::Effekseer::SIMD::AlignedAllocationPolicy<16> { protected: RENDERER* m_renderer; int32_t m_spriteCount; uint8_t* m_ringBufferData; struct KeyValue { float Key; efkSpriteInstanceParam Value; }; Effekseer::CustomAlignedVector instances; int32_t vertexCount_ = 0; int32_t stride_ = 0; int32_t instanceMaxCount_ = 0; int32_t customData1Count_ = 0; int32_t customData2Count_ = 0; public: SpriteRendererBase(RENDERER* renderer) : m_renderer(renderer) , m_spriteCount(0) , m_ringBufferData(nullptr) { // reserve buffers instances.reserve(m_renderer->GetSquareMaxCount()); } virtual ~SpriteRendererBase() { } protected: void RenderingInstance(const efkSpriteInstanceParam& instanceParameter, const efkSpriteNodeParam& parameter, const StandardRendererState& state, const ::Effekseer::SIMD::Mat44f& camera) { const ShaderParameterCollector& collector = state.Collector; if (collector.ShaderType == RendererShaderType::Material) { Rendering_Internal(parameter, instanceParameter, camera); } else if (collector.ShaderType == RendererShaderType::AdvancedLit) { Rendering_Internal(parameter, instanceParameter, camera); } else if (collector.ShaderType == RendererShaderType::AdvancedBackDistortion) { Rendering_Internal(parameter, instanceParameter, camera); } else if (collector.ShaderType == RendererShaderType::AdvancedUnlit) { Rendering_Internal(parameter, instanceParameter, camera); } else if (collector.ShaderType == RendererShaderType::Lit) { Rendering_Internal(parameter, instanceParameter, camera); } else if (collector.ShaderType == RendererShaderType::BackDistortion) { Rendering_Internal(parameter, instanceParameter, camera); } else { Rendering_Internal(parameter, instanceParameter, camera); } } void BeginRendering_(RENDERER* renderer, int32_t count, const efkSpriteNodeParam& param, void* userData) { EffekseerRenderer::StandardRendererState state; state.CullingType = ::Effekseer::CullingType::Double; state.DepthTest = param.ZTest; state.DepthWrite = param.ZWrite; state.Flipbook = ToState(param.BasicParameterPtr->Flipbook); state.UVDistortionIntensity = param.BasicParameterPtr->UVDistortionIntensity; state.TextureBlendType = param.BasicParameterPtr->TextureBlendType; state.BlendUVDistortionIntensity = param.BasicParameterPtr->BlendUVDistortionIntensity; state.EmissiveScaling = param.BasicParameterPtr->EmissiveScaling; state.EdgeThreshold = param.BasicParameterPtr->EdgeThreshold; state.EdgeColor[0] = param.BasicParameterPtr->EdgeColor[0]; state.EdgeColor[1] = param.BasicParameterPtr->EdgeColor[1]; state.EdgeColor[2] = param.BasicParameterPtr->EdgeColor[2]; state.EdgeColor[3] = param.BasicParameterPtr->EdgeColor[3]; state.EdgeColorScaling = param.BasicParameterPtr->EdgeColorScaling; state.IsAlphaCuttoffEnabled = param.BasicParameterPtr->IsAlphaCutoffEnabled; state.Maginification = param.Maginification; state.Distortion = param.BasicParameterPtr->MaterialType == Effekseer::RendererMaterialType::BackDistortion; state.DistortionIntensity = param.BasicParameterPtr->DistortionIntensity; state.MaterialType = param.BasicParameterPtr->MaterialType; state.RenderingUserData = param.UserData; state.HandleUserData = userData; state.LocalTime = param.LocalTime; state.CopyMaterialFromParameterToState( m_renderer, param.EffectPointer, param.BasicParameterPtr); customData1Count_ = state.CustomData1Count; customData2Count_ = state.CustomData2Count; instanceMaxCount_ = (std::min)(count, m_renderer->GetSquareMaxCount()); vertexCount_ = instanceMaxCount_ * 4; renderer->GetStandardRenderer()->BeginRenderingAndRenderingIfRequired(state, vertexCount_, stride_, (void*&)m_ringBufferData); m_spriteCount = 0; instances.clear(); } void Rendering_(const efkSpriteNodeParam& parameter, const efkSpriteInstanceParam& instanceParameter, const ::Effekseer::SIMD::Mat44f& camera) { if (parameter.ZSort == Effekseer::ZSortType::None) { auto cameraMat = m_renderer->GetCameraMatrix(); const auto& state = m_renderer->GetStandardRenderer()->GetState(); RenderingInstance(instanceParameter, parameter, state, cameraMat); } else { if (instances.size() >= instanceMaxCount_) { return; } KeyValue kv; kv.Value = instanceParameter; instances.push_back(kv); } } template void Rendering_Internal(const efkSpriteNodeParam& parameter, const efkSpriteInstanceParam& instanceParameter, const ::Effekseer::SIMD::Mat44f& camera) { if (m_ringBufferData == nullptr) return; StrideView verteies(m_ringBufferData, stride_, 4); for (int i = 0; i < 4; i++) { verteies[i].Pos.X = instanceParameter.Positions[i].GetX(); verteies[i].Pos.Y = instanceParameter.Positions[i].GetY(); verteies[i].Pos.Z = 0.0f; verteies[i].SetColor(instanceParameter.Colors[i], FLIP_RGB); verteies[i].SetFlipbookIndexAndNextRate(instanceParameter.FlipbookIndexAndNextRate); verteies[i].SetAlphaThreshold(instanceParameter.AlphaThreshold); } verteies[0].UV[0] = instanceParameter.UV.X; verteies[0].UV[1] = instanceParameter.UV.Y + instanceParameter.UV.Height; verteies[1].UV[0] = instanceParameter.UV.X + instanceParameter.UV.Width; verteies[1].UV[1] = instanceParameter.UV.Y + instanceParameter.UV.Height; verteies[2].UV[0] = instanceParameter.UV.X; verteies[2].UV[1] = instanceParameter.UV.Y; verteies[3].UV[0] = instanceParameter.UV.X + instanceParameter.UV.Width; verteies[3].UV[1] = instanceParameter.UV.Y; SetVertexAlphaUV(verteies[0], instanceParameter.AlphaUV.X, 0); SetVertexAlphaUV(verteies[0], instanceParameter.AlphaUV.Y + instanceParameter.AlphaUV.Height, 1); SetVertexAlphaUV(verteies[1], instanceParameter.AlphaUV.X + instanceParameter.AlphaUV.Width, 0); SetVertexAlphaUV(verteies[1], instanceParameter.AlphaUV.Y + instanceParameter.AlphaUV.Height, 1); SetVertexAlphaUV(verteies[2], instanceParameter.AlphaUV.X, 0); SetVertexAlphaUV(verteies[2], instanceParameter.AlphaUV.Y, 1); SetVertexAlphaUV(verteies[3], instanceParameter.AlphaUV.X + instanceParameter.AlphaUV.Width, 0); SetVertexAlphaUV(verteies[3], instanceParameter.AlphaUV.Y, 1); SetVertexUVDistortionUV(verteies[0], instanceParameter.UVDistortionUV.X, 0); SetVertexUVDistortionUV(verteies[0], instanceParameter.UVDistortionUV.Y + instanceParameter.UVDistortionUV.Height, 1); SetVertexUVDistortionUV(verteies[1], instanceParameter.UVDistortionUV.X + instanceParameter.UVDistortionUV.Width, 0); SetVertexUVDistortionUV(verteies[1], instanceParameter.UVDistortionUV.Y + instanceParameter.UVDistortionUV.Height, 1); SetVertexUVDistortionUV(verteies[2], instanceParameter.UVDistortionUV.X, 0); SetVertexUVDistortionUV(verteies[2], instanceParameter.UVDistortionUV.Y, 1); SetVertexUVDistortionUV(verteies[3], instanceParameter.UVDistortionUV.X + instanceParameter.UVDistortionUV.Width, 0); SetVertexUVDistortionUV(verteies[3], instanceParameter.UVDistortionUV.Y, 1); SetVertexBlendUV(verteies[0], instanceParameter.BlendUV.X, 0); SetVertexBlendUV(verteies[0], instanceParameter.BlendUV.Y + instanceParameter.BlendUV.Height, 1); SetVertexBlendUV(verteies[1], instanceParameter.BlendUV.X + instanceParameter.BlendUV.Width, 0); SetVertexBlendUV(verteies[1], instanceParameter.BlendUV.Y + instanceParameter.BlendUV.Height, 1); SetVertexBlendUV(verteies[2], instanceParameter.BlendUV.X, 0); SetVertexBlendUV(verteies[2], instanceParameter.BlendUV.Y, 1); SetVertexBlendUV(verteies[3], instanceParameter.BlendUV.X + instanceParameter.BlendUV.Width, 0); SetVertexBlendUV(verteies[3], instanceParameter.BlendUV.Y, 1); SetVertexBlendAlphaUV(verteies[0], instanceParameter.BlendAlphaUV.X, 0); SetVertexBlendAlphaUV(verteies[0], instanceParameter.BlendAlphaUV.Y + instanceParameter.BlendAlphaUV.Height, 1); SetVertexBlendAlphaUV(verteies[1], instanceParameter.BlendAlphaUV.X + instanceParameter.BlendAlphaUV.Width, 0); SetVertexBlendAlphaUV(verteies[1], instanceParameter.BlendAlphaUV.Y + instanceParameter.BlendAlphaUV.Height, 1); SetVertexBlendAlphaUV(verteies[2], instanceParameter.BlendAlphaUV.X, 0); SetVertexBlendAlphaUV(verteies[2], instanceParameter.BlendAlphaUV.Y, 1); SetVertexBlendAlphaUV(verteies[3], instanceParameter.BlendAlphaUV.X + instanceParameter.BlendAlphaUV.Width, 0); SetVertexBlendAlphaUV(verteies[3], instanceParameter.BlendAlphaUV.Y, 1); SetVertexBlendUVDistortionUV(verteies[0], instanceParameter.BlendUVDistortionUV.X, 0); SetVertexBlendUVDistortionUV(verteies[0], instanceParameter.BlendUVDistortionUV.Y + instanceParameter.BlendUVDistortionUV.Height, 1); SetVertexBlendUVDistortionUV(verteies[1], instanceParameter.BlendUVDistortionUV.X + instanceParameter.BlendUVDistortionUV.Width, 0); SetVertexBlendUVDistortionUV(verteies[1], instanceParameter.BlendUVDistortionUV.Y + instanceParameter.BlendUVDistortionUV.Height, 1); SetVertexBlendUVDistortionUV(verteies[2], instanceParameter.BlendUVDistortionUV.X, 0); SetVertexBlendUVDistortionUV(verteies[2], instanceParameter.BlendUVDistortionUV.Y, 1); SetVertexBlendUVDistortionUV(verteies[3], instanceParameter.BlendUVDistortionUV.X + instanceParameter.BlendUVDistortionUV.Width, 0); SetVertexBlendUVDistortionUV(verteies[3], instanceParameter.BlendUVDistortionUV.Y, 1); if (VertexUV2Required()) { StrideView vs(verteies.pointerOrigin_, stride_, 4); vs[0].SetUV2(0.0f, 1.0f); vs[1].SetUV2(1.0f, 1.0f); vs[2].SetUV2(0.0f, 0.0f); vs[3].SetUV2(1.0f, 0.0f); } if (parameter.Billboard == ::Effekseer::BillboardType::Billboard || parameter.Billboard == ::Effekseer::BillboardType::RotatedBillboard || parameter.Billboard == ::Effekseer::BillboardType::YAxisFixed) { Effekseer::SIMD::Mat43f mat_rot = Effekseer::SIMD::Mat43f::Identity; Effekseer::SIMD::Vec3f s; Effekseer::SIMD::Vec3f R; Effekseer::SIMD::Vec3f F; if (parameter.EnableViewOffset == true) { Effekseer::SIMD::Mat43f instMat = instanceParameter.SRTMatrix43; ApplyViewOffset(instMat, camera, instanceParameter.ViewOffsetDistance); CalcBillboard(parameter.Billboard, mat_rot, s, R, F, instMat, m_renderer->GetCameraFrontDirection()); } else { CalcBillboard(parameter.Billboard, mat_rot, s, R, F, instanceParameter.SRTMatrix43, m_renderer->GetCameraFrontDirection()); } for (int i = 0; i < 4; i++) { verteies[i].Pos.X = verteies[i].Pos.X * s.GetX(); verteies[i].Pos.Y = verteies[i].Pos.Y * s.GetY(); } ApplyDepthParameters(mat_rot, m_renderer->GetCameraFrontDirection(), m_renderer->GetCameraPosition(), s, parameter.DepthParameterPtr, parameter.IsRightHand); TransformVertexes(verteies, 4, mat_rot); if (VertexNormalRequired()) { if (!parameter.IsRightHand) { // It has a bug. But it is difficult to fix F = -F; R = -R; } StrideView vs(verteies.pointerOrigin_, stride_, 4); for (auto i = 0; i < 4; i++) { vs[i].SetPackedNormal(PackVector3DF(F), FLIP_RGB); vs[i].SetPackedTangent(PackVector3DF(R), FLIP_RGB); } } } else if (parameter.Billboard == ::Effekseer::BillboardType::Fixed) { auto mat = instanceParameter.SRTMatrix43; if (parameter.EnableViewOffset == true) { ApplyViewOffset(mat, camera, instanceParameter.ViewOffsetDistance); } ApplyDepthParameters(mat, m_renderer->GetCameraFrontDirection(), m_renderer->GetCameraPosition(), parameter.DepthParameterPtr, parameter.IsRightHand); for (int i = 0; i < 4; i++) { auto Pos = ::Effekseer::SIMD::Vec3f::Load(&verteies[i].Pos); Pos = ::Effekseer::SIMD::Vec3f::Transform(Pos, mat); ::Effekseer::SIMD::Vec3f::Store(&verteies[i].Pos, Pos); if (VertexNormalRequired()) { StrideView vs(verteies.pointerOrigin_, stride_, 4); auto tangentX = efkVector3D(mat.X.GetX(), mat.Y.GetX(), mat.Z.GetX()); auto tangentZ = efkVector3D(mat.X.GetZ(), mat.Y.GetZ(), mat.Z.GetZ()); tangentX = tangentX.Normalize(); tangentZ = tangentZ.Normalize(); if (!parameter.IsRightHand) { // It has a bug. But it is difficult to fix tangentX = -tangentX; tangentZ = -tangentZ; } vs[i].SetPackedNormal(PackVector3DF(tangentZ), FLIP_RGB); vs[i].SetPackedTangent(PackVector3DF(tangentX), FLIP_RGB); } } } // custom parameter if (customData1Count_ > 0) { StrideView custom(m_ringBufferData + sizeof(DynamicVertex), stride_, 4); for (int i = 0; i < 4; i++) { auto c = (float*)(&custom[i]); memcpy(c, instanceParameter.CustomData1.data(), sizeof(float) * customData1Count_); } } if (customData2Count_ > 0) { StrideView custom(m_ringBufferData + sizeof(DynamicVertex) + sizeof(float) * customData1Count_, stride_, 4); for (int i = 0; i < 4; i++) { auto c = (float*)(&custom[i]); memcpy(c, instanceParameter.CustomData2.data(), sizeof(float) * customData2Count_); } } m_ringBufferData += (stride_ * 4); m_spriteCount++; } void EndRendering_(RENDERER* renderer, const efkSpriteNodeParam& param) { if (param.ZSort != Effekseer::ZSortType::None) { for (auto& kv : instances) { efkVector3D t = kv.Value.SRTMatrix43.GetTranslation(); auto frontDirection = m_renderer->GetCameraFrontDirection(); if (!param.IsRightHand) { frontDirection = -frontDirection; } kv.Key = Effekseer::SIMD::Vec3f::Dot(t, frontDirection); } if (param.ZSort == Effekseer::ZSortType::NormalOrder) { std::sort(instances.begin(), instances.end(), [](const KeyValue& a, const KeyValue& b) -> bool { return a.Key < b.Key; }); } else { std::sort(instances.begin(), instances.end(), [](const KeyValue& a, const KeyValue& b) -> bool { return a.Key > b.Key; }); } for (auto& kv : instances) { auto camera = m_renderer->GetCameraMatrix(); const auto& state = renderer->GetStandardRenderer()->GetState(); RenderingInstance(kv.Value, param, state, camera); } } } public: void BeginRendering(const efkSpriteNodeParam& parameter, int32_t count, void* userData) override { BeginRendering_(m_renderer, count, parameter, userData); } void Rendering(const efkSpriteNodeParam& parameter, const efkSpriteInstanceParam& instanceParameter, void* userData) override { if (m_ringBufferData == nullptr) return; if (m_spriteCount == m_renderer->GetSquareMaxCount()) return; Rendering_(parameter, instanceParameter, m_renderer->GetCameraMatrix()); } void EndRendering(const efkSpriteNodeParam& parameter, void* userData) override { if (m_ringBufferData == nullptr) return; EndRendering_(m_renderer, parameter); } }; //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- } // namespace EffekseerRenderer //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- #endif // __EFFEKSEERRENDERER_SPRITE_RENDERER_H__