mirror of https://github.com/axmolengine/axmol.git
472 lines
17 KiB
C++
472 lines
17 KiB
C++
|
|
#ifndef __EFFEKSEERRENDERER_SPRITE_RENDERER_BASE_H__
|
|
#define __EFFEKSEERRENDERER_SPRITE_RENDERER_BASE_H__
|
|
|
|
//----------------------------------------------------------------------------------
|
|
// Include
|
|
//----------------------------------------------------------------------------------
|
|
#include <Effekseer.h>
|
|
#include <algorithm>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <string.h>
|
|
|
|
#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 <typename RENDERER, bool FLIP_RGB_FLAG>
|
|
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<KeyValue> 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<DynamicVertex, FLIP_RGB_FLAG>(parameter, instanceParameter, camera);
|
|
}
|
|
else if (collector.ShaderType == RendererShaderType::AdvancedLit)
|
|
{
|
|
Rendering_Internal<AdvancedLightingVertex, FLIP_RGB_FLAG>(parameter, instanceParameter, camera);
|
|
}
|
|
else if (collector.ShaderType == RendererShaderType::AdvancedBackDistortion)
|
|
{
|
|
Rendering_Internal<AdvancedLightingVertex, FLIP_RGB_FLAG>(parameter, instanceParameter, camera);
|
|
}
|
|
else if (collector.ShaderType == RendererShaderType::AdvancedUnlit)
|
|
{
|
|
Rendering_Internal<AdvancedSimpleVertex, FLIP_RGB_FLAG>(parameter, instanceParameter, camera);
|
|
}
|
|
else if (collector.ShaderType == RendererShaderType::Lit)
|
|
{
|
|
Rendering_Internal<LightingVertex, FLIP_RGB_FLAG>(parameter, instanceParameter, camera);
|
|
}
|
|
else if (collector.ShaderType == RendererShaderType::BackDistortion)
|
|
{
|
|
Rendering_Internal<LightingVertex, FLIP_RGB_FLAG>(parameter, instanceParameter, camera);
|
|
}
|
|
else
|
|
{
|
|
Rendering_Internal<SimpleVertex, FLIP_RGB_FLAG>(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 <typename VERTEX, bool FLIP_RGB>
|
|
void Rendering_Internal(const efkSpriteNodeParam& parameter,
|
|
const efkSpriteInstanceParam& instanceParameter,
|
|
const ::Effekseer::SIMD::Mat44f& camera)
|
|
{
|
|
if (m_ringBufferData == nullptr)
|
|
return;
|
|
|
|
StrideView<VERTEX> 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<VERTEX>())
|
|
{
|
|
StrideView<VERTEX> 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<VERTEX>())
|
|
{
|
|
if (!parameter.IsRightHand)
|
|
{
|
|
// It has a bug. But it is difficult to fix
|
|
F = -F;
|
|
R = -R;
|
|
}
|
|
|
|
StrideView<VERTEX> 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<VERTEX>())
|
|
{
|
|
StrideView<VERTEX> 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<float> 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<float> 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__
|