#ifndef __EFFEKSEERRENDERER_MODEL_RENDERER_BASE_H__ #define __EFFEKSEERRENDERER_MODEL_RENDERER_BASE_H__ #include #include #include #include #include #include "EffekseerRenderer.CommonUtils.h" #include "EffekseerRenderer.IndexBufferBase.h" #include "EffekseerRenderer.RenderStateBase.h" #include "EffekseerRenderer.Renderer.h" #include "EffekseerRenderer.VertexBufferBase.h" namespace EffekseerRenderer { typedef ::Effekseer::ModelRenderer::NodeParameter efkModelNodeParam; typedef ::Effekseer::ModelRenderer::InstanceParameter efkModelInstanceParam; typedef ::Effekseer::SIMD::Vec3f efkVector3D; template struct ModelRendererVertexConstantBuffer { Effekseer::Matrix44 CameraMatrix; Effekseer::Matrix44 ModelMatrix[MODEL_COUNT]; float ModelUV[MODEL_COUNT][4]; void SetModelFlipbookParameter(const Effekseer::NodeRendererFlipbookParameter& param) { } void SetModelAlphaUV(int32_t index, float x, float y, float w, float h) { } void SetModelUVDistortionUV(int32_t index, float x, float y, float w, float h) { } void SetModelBlendUV(int32_t index, float x, float y, float w, float h) { } void SetModelBlendAlphaUV(int32_t index, float x, float y, float w, float h) { } void SetModelBlendUVDistortionUV(int32_t index, float x, float y, float w, float h) { } void SetModelFlipbookIndexAndNextRate(int32_t index, float value) { } void SetModelAlphaThreshold(int32_t index, float value) { } float ModelColor[MODEL_COUNT][4]; float LightDirection[4]; float LightColor[4]; float LightAmbientColor[4]; float UVInversed[4]; }; template struct ModelRendererAdvancedVertexConstantBuffer { Effekseer::Matrix44 CameraMatrix; Effekseer::Matrix44 ModelMatrix[MODEL_COUNT]; float ModelUV[MODEL_COUNT][4]; float ModelAlphaUV[MODEL_COUNT][4]; float ModelUVDistortionUV[MODEL_COUNT][4]; float ModelBlendUV[MODEL_COUNT][4]; float ModelBlendAlphaUV[MODEL_COUNT][4]; float ModelBlendUVDistortionUV[MODEL_COUNT][4]; FlipbookVertexBuffer ModelFlipbookParameter; float ModelFlipbookIndexAndNextRate[MODEL_COUNT][4]; float ModelAlphaThreshold[MODEL_COUNT][4]; void SetModelFlipbookParameter(const Effekseer::NodeRendererFlipbookParameter& param) { const auto state = ToState(param); ModelFlipbookParameter = ToVertexBuffer(state); } void SetModelAlphaUV(int32_t index, float x, float y, float w, float h) { ModelAlphaUV[index][0] = x; ModelAlphaUV[index][1] = y; ModelAlphaUV[index][2] = w; ModelAlphaUV[index][3] = h; } void SetModelUVDistortionUV(int32_t index, float x, float y, float w, float h) { ModelUVDistortionUV[index][0] = x; ModelUVDistortionUV[index][1] = y; ModelUVDistortionUV[index][2] = w; ModelUVDistortionUV[index][3] = h; } void SetModelBlendUV(int32_t index, float x, float y, float w, float h) { ModelBlendUV[index][0] = x; ModelBlendUV[index][1] = y; ModelBlendUV[index][2] = w; ModelBlendUV[index][3] = h; } void SetModelBlendAlphaUV(int32_t index, float x, float y, float w, float h) { ModelBlendAlphaUV[index][0] = x; ModelBlendAlphaUV[index][1] = y; ModelBlendAlphaUV[index][2] = w; ModelBlendAlphaUV[index][3] = h; } void SetModelBlendUVDistortionUV(int32_t index, float x, float y, float w, float h) { ModelBlendUVDistortionUV[index][0] = x; ModelBlendUVDistortionUV[index][1] = y; ModelBlendUVDistortionUV[index][2] = w; ModelBlendUVDistortionUV[index][3] = h; } void SetModelFlipbookIndexAndNextRate(int32_t index, float value) { ModelFlipbookIndexAndNextRate[index][0] = value; } void SetModelAlphaThreshold(int32_t index, float value) { ModelAlphaThreshold[index][0] = value; } float ModelColor[MODEL_COUNT][4]; float LightDirection[4]; float LightColor[4]; float LightAmbientColor[4]; float UVInversed[4]; }; template struct ModelRendererMaterialVertexConstantBuffer { Effekseer::Matrix44 CameraMatrix; Effekseer::Matrix44 ModelMatrix[MODEL_COUNT]; float ModelUV[MODEL_COUNT][4]; float ModelColor[MODEL_COUNT][4]; float LightDirection[4]; float LightColor[4]; float LightAmbientColor[4]; float UVInversed[4]; void SetModelFlipbookParameter(const Effekseer::NodeRendererFlipbookParameter& param) { } void SetModelAlphaUV(int32_t index, float x, float y, float w, float h) { } void SetModelUVDistortionUV(int32_t index, float x, float y, float w, float h) { } void SetModelBlendUV(int32_t iondex, float x, float y, float w, float h) { } void SetModelBlendAlphaUV(int32_t iondex, float x, float y, float w, float h) { } void SetModelBlendUVDistortionUV(int32_t iondex, float x, float y, float w, float h) { } void SetModelFlipbookIndexAndNextRate(int32_t index, float value) { } void SetModelAlphaThreshold(int32_t index, float value) { } }; enum class ModelRendererVertexType { Instancing, Single, }; class ModelRendererBase : public ::Effekseer::ModelRenderer, public ::Effekseer::SIMD::AlignedAllocationPolicy<16> { protected: struct KeyValue { float Key; int Value; }; std::vector keyValues_; std::vector matrixesSorted_; std::vector uvSorted_; std::vector alphaUVSorted_; std::vector uvDistortionUVSorted_; std::vector blendUVSorted_; std::vector blendAlphaUVSorted_; std::vector blendUVDistortionUVSorted_; std::vector flipbookIndexAndNextRateSorted_; std::vector alphaThresholdSorted_; std::vector viewOffsetDistanceSorted_; std::vector colorsSorted_; std::vector timesSorted_; std::vector> customData1Sorted_; std::vector> customData2Sorted_; std::vector m_matrixes; std::vector m_uv; std::vector m_alphaUV; std::vector m_uvDistortionUV; std::vector m_blendUV; std::vector m_blendAlphaUV; std::vector m_blendUVDistortionUV; std::vector m_flipbookIndexAndNextRate; std::vector m_alphaThreshold; std::vector m_viewOffsetDistance; std::vector m_colors; std::vector m_times; std::vector> customData1_; std::vector> customData2_; int32_t customData1Count_ = 0; int32_t customData2Count_ = 0; ShaderParameterCollector collector_; void ColorToFloat4(::Effekseer::Color color, float fc[4]) { fc[0] = color.R / 255.0f; fc[1] = color.G / 255.0f; fc[2] = color.B / 255.0f; fc[3] = color.A / 255.0f; } std::array ColorToFloat4(::Effekseer::Color color) { std::array fc; fc[0] = color.R / 255.0f; fc[1] = color.G / 255.0f; fc[2] = color.B / 255.0f; fc[3] = color.A / 255.0f; return fc; } void VectorToFloat4(const ::Effekseer::SIMD::Vec3f& v, float fc[4]) { ::Effekseer::SIMD::Float4::Store3(fc, v.s); fc[3] = 1.0f; } void VectorToFloat4(const ::Effekseer::SIMD::Vec3f& v, std::array& fc) { ::Effekseer::SIMD::Float4::Store3(fc.data(), v.s); fc[3] = 1.0f; } ModelRendererBase() { } template void GetInversedFlags(RENDERER* renderer, std::array& uvInversed, std::array& uvInversedBack) { if (renderer->GetTextureUVStyle() == UVStyle::VerticalFlipped) { uvInversed[0] = 1.0f; uvInversed[1] = -1.0f; } else { uvInversed[0] = 0.0f; uvInversed[1] = 1.0f; } if (renderer->GetBackgroundTextureUVStyle() == UVStyle::VerticalFlipped) { uvInversedBack[0] = 1.0f; uvInversedBack[1] = -1.0f; } else { uvInversedBack[0] = 0.0f; uvInversedBack[1] = 1.0f; } } template void SortTemporaryValues(RENDERER* renderer, const efkModelNodeParam& param) { if (param.DepthParameterPtr->ZSort != Effekseer::ZSortType::None) { keyValues_.resize(m_matrixes.size()); for (size_t i = 0; i < keyValues_.size(); i++) { efkVector3D t(m_matrixes[i].Values[3][0], m_matrixes[i].Values[3][1], m_matrixes[i].Values[3][2]); auto frontDirection = renderer->GetCameraFrontDirection(); if (!param.IsRightHand) { frontDirection = -frontDirection; } keyValues_[i].Key = Effekseer::SIMD::Vec3f::Dot(t, frontDirection); keyValues_[i].Value = static_cast(i); } if (param.DepthParameterPtr->ZSort == Effekseer::ZSortType::NormalOrder) { std::sort(keyValues_.begin(), keyValues_.end(), [](const KeyValue& a, const KeyValue& b) -> bool { return a.Key < b.Key; }); } else { std::sort(keyValues_.begin(), keyValues_.end(), [](const KeyValue& a, const KeyValue& b) -> bool { return a.Key > b.Key; }); } matrixesSorted_.resize(m_matrixes.size()); uvSorted_.resize(m_matrixes.size()); alphaUVSorted_.resize(m_matrixes.size()); uvDistortionUVSorted_.resize(m_matrixes.size()); blendUVSorted_.resize(m_matrixes.size()); blendAlphaUVSorted_.resize(m_matrixes.size()); blendUVDistortionUVSorted_.resize(m_matrixes.size()); flipbookIndexAndNextRateSorted_.resize(m_matrixes.size()); alphaThresholdSorted_.resize(m_matrixes.size()); viewOffsetDistanceSorted_.resize(m_matrixes.size()); colorsSorted_.resize(m_matrixes.size()); timesSorted_.resize(m_matrixes.size()); if (customData1Count_ > 0) { customData1Sorted_.resize(m_matrixes.size()); } if (customData2Count_ > 0) { customData2Sorted_.resize(m_matrixes.size()); } for (size_t i = 0; i < keyValues_.size(); i++) { matrixesSorted_[keyValues_[i].Value] = m_matrixes[i]; uvSorted_[keyValues_[i].Value] = m_uv[i]; alphaUVSorted_[keyValues_[i].Value] = m_alphaUV[i]; uvDistortionUVSorted_[keyValues_[i].Value] = m_uvDistortionUV[i]; blendUVSorted_[keyValues_[i].Value] = m_blendUV[i]; blendAlphaUVSorted_[keyValues_[i].Value] = m_blendAlphaUV[i]; blendUVDistortionUVSorted_[keyValues_[i].Value] = m_blendUVDistortionUV[i]; flipbookIndexAndNextRateSorted_[keyValues_[i].Value] = m_flipbookIndexAndNextRate[i]; alphaThresholdSorted_[keyValues_[i].Value] = m_alphaThreshold[i]; viewOffsetDistanceSorted_[keyValues_[i].Value] = m_viewOffsetDistance[i]; colorsSorted_[keyValues_[i].Value] = m_colors[i]; timesSorted_[keyValues_[i].Value] = m_times[i]; } if (customData1Count_ > 0) { for (size_t i = 0; i < keyValues_.size(); i++) { customData1Sorted_[keyValues_[i].Value] = customData1_[i]; } } if (customData2Count_ > 0) { for (size_t i = 0; i < keyValues_.size(); i++) { customData2Sorted_[keyValues_[i].Value] = customData2_[i]; } } m_matrixes = matrixesSorted_; m_uv = uvSorted_; m_alphaUV = alphaUVSorted_; m_uvDistortionUV = uvDistortionUVSorted_; m_blendUV = blendUVSorted_; m_blendAlphaUV = blendAlphaUVSorted_; m_blendUVDistortionUV = blendUVDistortionUVSorted_; m_flipbookIndexAndNextRate = flipbookIndexAndNextRateSorted_; m_alphaThreshold = alphaThresholdSorted_; m_viewOffsetDistance = viewOffsetDistanceSorted_; m_colors = colorsSorted_; m_times = timesSorted_; customData1_ = customData1Sorted_; customData2_ = customData2Sorted_; } } template void StoreFileUniform(RENDERER* renderer, SHADER* shader_, Effekseer::MaterialRef material, Effekseer::MaterialRenderData* materialRenderData, const efkModelNodeParam& param, int32_t renderPassInd, float*& cutomData1Ptr, float*& cutomData2Ptr) { std::array uvInversed; std::array uvInversedBack; cutomData1Ptr = nullptr; cutomData2Ptr = nullptr; const auto materialGradientCount = static_cast(Effekseer::Min(materialRenderData->MaterialGradients.size(), Effekseer::UserGradientSlotMax)); GetInversedFlags(renderer, uvInversed, uvInversedBack); std::array uvInversedMaterial; uvInversedMaterial[0] = uvInversed[0]; uvInversedMaterial[1] = uvInversed[1]; uvInversedMaterial[2] = uvInversedBack[0]; uvInversedMaterial[3] = uvInversedBack[1]; // camera float cameraPosition[4]; ::Effekseer::SIMD::Vec3f cameraPosition3 = renderer->GetCameraPosition(); VectorToFloat4(cameraPosition3, cameraPosition); // time std::array predefined_uniforms; predefined_uniforms.fill(0.5f); predefined_uniforms[0] = renderer->GetTime(); predefined_uniforms[1] = param.Magnification; predefined_uniforms[2] = renderer->GetImpl()->MaintainGammaColorInLinearColorSpace ? 1.0f : 0.0f; predefined_uniforms[3] = param.LocalTime; // vs int32_t vsOffset = sizeof(Effekseer::Matrix44) + (sizeof(Effekseer::Matrix44) + sizeof(float) * 4 * 2) * InstanceCount; renderer->SetVertexBufferToShader(uvInversedMaterial.data(), sizeof(float) * 4, vsOffset); vsOffset += (sizeof(float) * 4); renderer->SetVertexBufferToShader(predefined_uniforms.data(), sizeof(float) * 4, vsOffset); vsOffset += (sizeof(float) * 4); renderer->SetVertexBufferToShader(cameraPosition, sizeof(float) * 4, vsOffset); vsOffset += (sizeof(float) * 4); // vs - custom data if (customData1Count_ > 0) { cutomData1Ptr = (float*)((uint8_t*)shader_->GetVertexConstantBuffer() + vsOffset); vsOffset += (sizeof(float) * 4) * InstanceCount; } if (customData2Count_ > 0) { cutomData2Ptr = (float*)((uint8_t*)shader_->GetVertexConstantBuffer() + vsOffset); vsOffset += (sizeof(float) * 4) * InstanceCount; } for (size_t i = 0; i < materialRenderData->MaterialUniforms.size(); i++) { renderer->SetVertexBufferToShader(materialRenderData->MaterialUniforms[i].data(), sizeof(float) * 4, vsOffset); vsOffset += (sizeof(float) * 4); } for (size_t i = 0; i < materialGradientCount; i++) { auto data = ToUniform(*materialRenderData->MaterialGradients[i]); renderer->SetVertexBufferToShader(data.data(), sizeof(float) * 4 * 13, vsOffset); vsOffset += (sizeof(float) * 4) * 13; } // ps int32_t psOffset = 0; renderer->SetPixelBufferToShader(uvInversedMaterial.data(), sizeof(float) * 4, psOffset); psOffset += (sizeof(float) * 4); renderer->SetPixelBufferToShader(predefined_uniforms.data(), sizeof(float) * 4, psOffset); psOffset += (sizeof(float) * 4); renderer->SetPixelBufferToShader(cameraPosition, sizeof(float) * 4, psOffset); psOffset += (sizeof(float) * 4); ::Effekseer::Backend::TextureRef depthTexture = nullptr; ::EffekseerRenderer::DepthReconstructionParameter reconstructionParam; renderer->GetImpl()->GetDepth(depthTexture, reconstructionParam); SoftParticleParameter softParticleParam; softParticleParam.SetParam( 0.0f, 0.0f, 0.0f, param.Maginification, reconstructionParam.DepthBufferScale, reconstructionParam.DepthBufferOffset, reconstructionParam.ProjectionMatrix33, reconstructionParam.ProjectionMatrix34, reconstructionParam.ProjectionMatrix43, reconstructionParam.ProjectionMatrix44); renderer->SetPixelBufferToShader(softParticleParam.reconstructionParam1.data(), sizeof(float) * 4, psOffset); psOffset += (sizeof(float) * 4); renderer->SetPixelBufferToShader(softParticleParam.reconstructionParam2.data(), sizeof(float) * 4, psOffset); psOffset += (sizeof(float) * 4); // shader model material = param.EffectPointer->GetMaterial(materialRenderData->MaterialIndex); float lightDirection[4]; float lightColor[4]; float lightAmbientColor[4]; ::Effekseer::SIMD::Vec3f lightDirection3 = renderer->GetLightDirection(); lightDirection3 = lightDirection3.Normalize(); VectorToFloat4(lightDirection3, lightDirection); ColorToFloat4(renderer->GetLightColor(), lightColor); ColorToFloat4(renderer->GetLightAmbientColor(), lightAmbientColor); renderer->SetPixelBufferToShader(lightDirection, sizeof(float) * 4, psOffset); psOffset += (sizeof(float) * 4); renderer->SetPixelBufferToShader(lightColor, sizeof(float) * 4, psOffset); psOffset += (sizeof(float) * 4); renderer->SetPixelBufferToShader(lightAmbientColor, sizeof(float) * 4, psOffset); psOffset += (sizeof(float) * 4); // refraction if (material->RefractionModelUserPtr != nullptr && renderPassInd == 0) { auto mat = renderer->GetCameraMatrix(); renderer->SetPixelBufferToShader(&mat, sizeof(float) * 16, psOffset); psOffset += (sizeof(float) * 16); } for (size_t i = 0; i < materialRenderData->MaterialUniforms.size(); i++) { renderer->SetPixelBufferToShader(materialRenderData->MaterialUniforms[i].data(), sizeof(float) * 4, psOffset); psOffset += (sizeof(float) * 4); } for (int32_t i = 0; i < materialGradientCount; i++) { auto data = ToUniform(*materialRenderData->MaterialGradients[i]); renderer->SetPixelBufferToShader(data.data(), sizeof(float) * 4 * 13, psOffset); psOffset += (sizeof(float) * 4) * 13; } } template void StoreFixedUniforms(RENDERER* renderer, SHADER* shader_, const efkModelNodeParam& param) { VertexConstantBufferType* vcb = (VertexConstantBufferType*)shader_->GetVertexConstantBuffer(); std::array uvInversed; std::array uvInversedBack; GetInversedFlags(renderer, uvInversed, uvInversedBack); vcb->UVInversed[0] = uvInversed[0]; vcb->UVInversed[1] = uvInversed[1]; ::Effekseer::Backend::TextureRef depthTexture = nullptr; ::EffekseerRenderer::DepthReconstructionParameter reconstructionParam; renderer->GetImpl()->GetDepth(depthTexture, reconstructionParam); if (DISTORTION) { auto pcb = (PixelConstantBufferDistortion*)shader_->GetPixelConstantBuffer(); pcb->DistortionIntencity[0] = param.BasicParameterPtr->DistortionIntensity; pcb->UVInversedBack[0] = uvInversedBack[0]; pcb->UVInversedBack[1] = uvInversedBack[1]; pcb->FlipbookParam.EnableInterpolation = static_cast(param.BasicParameterPtr->Flipbook.EnableInterpolation); pcb->FlipbookParam.InterpolationType = static_cast(param.BasicParameterPtr->Flipbook.InterpolationType); pcb->UVDistortionParam.Intensity = param.BasicParameterPtr->UVDistortionIntensity; pcb->UVDistortionParam.BlendIntensity = param.BasicParameterPtr->BlendUVDistortionIntensity; pcb->UVDistortionParam.UVInversed[0] = uvInversed[0]; pcb->UVDistortionParam.UVInversed[1] = uvInversed[1]; pcb->BlendTextureParam.BlendType = static_cast(param.BasicParameterPtr->TextureBlendType); pcb->SoftParticleParam.SetParam( param.BasicParameterPtr->SoftParticleDistanceFar, param.BasicParameterPtr->SoftParticleDistanceNear, param.BasicParameterPtr->SoftParticleDistanceNearOffset, param.Maginification, reconstructionParam.DepthBufferScale, reconstructionParam.DepthBufferOffset, reconstructionParam.ProjectionMatrix33, reconstructionParam.ProjectionMatrix34, reconstructionParam.ProjectionMatrix43, reconstructionParam.ProjectionMatrix44); } else { auto pcb = (PixelConstantBuffer*)shader_->GetPixelConstantBuffer(); pcb->MiscFlags.fill(0.0f); pcb->MiscFlags[0] = renderer->GetImpl()->MaintainGammaColorInLinearColorSpace ? 1.0f : 0.0f; // specify predefined parameters if (param.BasicParameterPtr->MaterialType == Effekseer::RendererMaterialType::Lighting) { ::Effekseer::SIMD::Vec3f lightDirection = renderer->GetLightDirection(); lightDirection = lightDirection.Normalize(); VectorToFloat4(lightDirection, vcb->LightDirection); VectorToFloat4(lightDirection, pcb->LightDirection); } { ColorToFloat4(renderer->GetLightColor(), vcb->LightColor); pcb->LightColor = ColorToFloat4(renderer->GetLightColor()); } { ColorToFloat4(renderer->GetLightAmbientColor(), vcb->LightAmbientColor); pcb->LightAmbientColor = ColorToFloat4(renderer->GetLightAmbientColor()); } pcb->SetEmissiveScaling(static_cast(param.BasicParameterPtr->EmissiveScaling)); if (REQUIRE_ADVANCED_DATA) { pcb->SetModelFlipbookParameter(param.BasicParameterPtr->Flipbook.EnableInterpolation, static_cast(param.BasicParameterPtr->Flipbook.InterpolationType)); pcb->SetModelUVDistortionParameter(param.BasicParameterPtr->UVDistortionIntensity, param.BasicParameterPtr->BlendUVDistortionIntensity, {uvInversed[0], uvInversed[1]}); pcb->SetModelBlendTextureParameter(static_cast(param.BasicParameterPtr->TextureBlendType)); ::Effekseer::Vector3D CameraFront = renderer->GetCameraFrontDirection(); if (!param.IsRightHand) { CameraFront = -CameraFront; } pcb->SetCameraFrontDirection(-CameraFront.X, -CameraFront.Y, -CameraFront.Z); pcb->SetFalloffParameter( static_cast(param.EnableFalloff), static_cast(param.FalloffParam.ColorBlendType), static_cast(param.FalloffParam.Pow), ColorToFloat4(param.FalloffParam.BeginColor), ColorToFloat4(param.FalloffParam.EndColor)); pcb->SetEdgeParameter(ColorToFloat4(Effekseer::Color( param.BasicParameterPtr->EdgeColor[0], param.BasicParameterPtr->EdgeColor[1], param.BasicParameterPtr->EdgeColor[2], param.BasicParameterPtr->EdgeColor[3])), param.BasicParameterPtr->EdgeThreshold, static_cast(param.BasicParameterPtr->EdgeColorScaling)); } pcb->SoftParticleParam.SetParam( param.BasicParameterPtr->SoftParticleDistanceFar, param.BasicParameterPtr->SoftParticleDistanceNear, param.BasicParameterPtr->SoftParticleDistanceNearOffset, param.Maginification, reconstructionParam.DepthBufferScale, reconstructionParam.DepthBufferOffset, reconstructionParam.ProjectionMatrix33, reconstructionParam.ProjectionMatrix34, reconstructionParam.ProjectionMatrix43, reconstructionParam.ProjectionMatrix44); pcb->UVInversedBack[0] = uvInversedBack[0]; pcb->UVInversedBack[1] = uvInversedBack[1]; } vcb->CameraMatrix = renderer->GetCameraProjectionMatrix(); vcb->SetModelFlipbookParameter(param.BasicParameterPtr->Flipbook); } public: ModelRendererVertexType VertexType = ModelRendererVertexType::Single; virtual ~ModelRendererBase() { } template void BeginRendering_(RENDERER* renderer, const efkModelNodeParam& parameter, int32_t count, void* userData) { keyValues_.clear(); m_matrixes.clear(); m_uv.clear(); m_alphaUV.clear(); m_uvDistortionUV.clear(); m_blendUV.clear(); m_blendAlphaUV.clear(); m_blendUVDistortionUV.clear(); m_flipbookIndexAndNextRate.clear(); m_alphaThreshold.clear(); m_viewOffsetDistance.clear(); m_colors.clear(); m_times.clear(); customData1_.clear(); customData2_.clear(); matrixesSorted_.clear(); uvSorted_.clear(); alphaUVSorted_.clear(); uvDistortionUVSorted_.clear(); blendUVSorted_.clear(); blendAlphaUVSorted_.clear(); blendUVDistortionUVSorted_.clear(); flipbookIndexAndNextRateSorted_.clear(); alphaThresholdSorted_.clear(); viewOffsetDistanceSorted_.clear(); colorsSorted_.clear(); timesSorted_.clear(); customData1Sorted_.clear(); customData2Sorted_.clear(); if (parameter.BasicParameterPtr->MaterialType == ::Effekseer::RendererMaterialType::File && parameter.BasicParameterPtr->MaterialRenderDataPtr != nullptr && parameter.BasicParameterPtr->MaterialRenderDataPtr->MaterialIndex >= 0 && parameter.EffectPointer->GetMaterial(parameter.BasicParameterPtr->MaterialRenderDataPtr->MaterialIndex) != nullptr) { auto material = parameter.EffectPointer->GetMaterial(parameter.BasicParameterPtr->MaterialRenderDataPtr->MaterialIndex); customData1Count_ = material->CustomData1; customData2Count_ = material->CustomData2; } else { customData1Count_ = 0; customData2Count_ = 0; } renderer->GetStandardRenderer()->ResetAndRenderingIfRequired(); collector_ = ShaderParameterCollector(); collector_.Collect(renderer, parameter.EffectPointer, parameter.BasicParameterPtr, parameter.EnableFalloff, renderer->GetImpl()->isSoftParticleEnabled); } template void Rendering_(RENDERER* renderer, const efkModelNodeParam& parameter, const efkModelInstanceParam& instanceParameter, void* userData) { ::Effekseer::BillboardType btype = parameter.Billboard; Effekseer::SIMD::Mat44f mat44; if (btype == ::Effekseer::BillboardType::Fixed) { mat44 = instanceParameter.SRTMatrix43; } else { Effekseer::SIMD::Mat43f mat43; Effekseer::SIMD::Vec3f s; Effekseer::SIMD::Vec3f R; Effekseer::SIMD::Vec3f F; CalcBillboard(btype, mat43, s, R, F, instanceParameter.SRTMatrix43, renderer->GetCameraFrontDirection()); mat44 = ::Effekseer::SIMD::Mat43f::Scaling(s) * mat43; } if (parameter.Magnification != 1.0f) { mat44 = Effekseer::SIMD::Mat44f::Scaling(::Effekseer::SIMD::Vec3f(parameter.Magnification)) * mat44; } if (!parameter.IsRightHand) { mat44 = Effekseer::SIMD::Mat44f::Scaling(1.0f, 1.0f, -1.0f) * mat44; } m_matrixes.push_back(ToStruct(mat44)); m_uv.push_back(instanceParameter.UV); m_alphaUV.push_back(instanceParameter.AlphaUV); m_uvDistortionUV.push_back(instanceParameter.UVDistortionUV); m_blendUV.push_back(instanceParameter.BlendUV); m_blendAlphaUV.push_back(instanceParameter.BlendAlphaUV); m_blendUVDistortionUV.push_back(instanceParameter.BlendUVDistortionUV); m_flipbookIndexAndNextRate.push_back(instanceParameter.FlipbookIndexAndNextRate); m_alphaThreshold.push_back(instanceParameter.AlphaThreshold); m_viewOffsetDistance.push_back(instanceParameter.ViewOffsetDistance); m_colors.push_back(instanceParameter.AllColor); m_times.push_back(instanceParameter.Time); if (customData1Count_ > 0) { customData1_.push_back(instanceParameter.CustomData1); } if (customData2Count_ > 0) { customData2_.push_back(instanceParameter.CustomData2); } //parameter.BasicParameterPtr } template void EndRendering_(RENDERER* renderer, SHADER* advanced_shader_lit, SHADER* advanced_shader_unlit, SHADER* advanced_shader_distortion, SHADER* shader_lit, SHADER* shader_unlit, SHADER* shader_distortion, const efkModelNodeParam& param, void* userData) { if (m_matrixes.size() == 0) return; if (param.ModelIndex < 0) return; if (renderer->GetExternalShaderSettings() == nullptr) { shader_unlit->OverrideShader(nullptr); } else { shader_unlit->OverrideShader(renderer->GetExternalShaderSettings()->ModelShader); } int32_t renderPassCount = 1; if (param.BasicParameterPtr->MaterialRenderDataPtr != nullptr && param.BasicParameterPtr->MaterialRenderDataPtr->MaterialIndex >= 0) { auto material = param.EffectPointer->GetMaterial(param.BasicParameterPtr->MaterialRenderDataPtr->MaterialIndex); if (material != nullptr && material->IsRefractionRequired) { // refraction, standard renderPassCount = 2; } } // sort SortTemporaryValues(renderer, param); for (int32_t renderPassInd = 0; renderPassInd < renderPassCount; renderPassInd++) { Effekseer::MaterialRenderData* materialRenderData = param.BasicParameterPtr->MaterialRenderDataPtr; if (materialRenderData != nullptr && materialRenderData->MaterialIndex >= 0 && param.EffectPointer->GetMaterial(materialRenderData->MaterialIndex) != nullptr) { RenderPass, false>( renderer, advanced_shader_lit, advanced_shader_unlit, advanced_shader_distortion, shader_lit, shader_unlit, shader_distortion, param, renderPassInd, userData); } else { if (collector_.DoRequireAdvancedRenderer()) { RenderPass, true>( renderer, advanced_shader_lit, advanced_shader_unlit, advanced_shader_distortion, shader_lit, shader_unlit, shader_distortion, param, renderPassInd, userData); } else { RenderPass, false>( renderer, advanced_shader_lit, advanced_shader_unlit, advanced_shader_distortion, shader_lit, shader_unlit, shader_distortion, param, renderPassInd, userData); } } } } template void RenderPass(RENDERER* renderer, SHADER* advanced_shader_lit, SHADER* advanced_shader_unlit, SHADER* advanced_shader_distortion, SHADER* shader_lit, SHADER* shader_unlit, SHADER* shader_distortion, const efkModelNodeParam& param, int32_t renderPassInd, void* userData) { if (m_matrixes.size() == 0) return; if (param.ModelIndex < 0) return; ::Effekseer::RefPtr model; if (param.IsProceduralMode) { model = param.EffectPointer->GetProceduralModel(param.ModelIndex); } else { model = param.EffectPointer->GetModel(param.ModelIndex); } if (model == nullptr) return; auto isBackgroundRequired = collector_.IsBackgroundRequiredOnFirstPass && renderPassInd == 0; if (isBackgroundRequired) { auto callback = renderer->GetDistortingCallback(); if (callback != nullptr) { if (!callback->OnDistorting(renderer)) { return; } } } auto distortion = collector_.ShaderType == EffekseerRenderer::RendererShaderType::BackDistortion || collector_.ShaderType == EffekseerRenderer::RendererShaderType::AdvancedBackDistortion; if (isBackgroundRequired && renderer->GetBackground() == 0) return; if (isBackgroundRequired) { collector_.Textures[collector_.BackgroundIndex] = renderer->GetBackground(); } ::Effekseer::Backend::TextureRef depthTexture = nullptr; ::EffekseerRenderer::DepthReconstructionParameter reconstructionParam; renderer->GetImpl()->GetDepth(depthTexture, reconstructionParam); if (collector_.IsDepthRequired) { if (depthTexture == nullptr || (param.BasicParameterPtr->SoftParticleDistanceFar == 0.0f && param.BasicParameterPtr->SoftParticleDistanceNear == 0.0f && param.BasicParameterPtr->SoftParticleDistanceNearOffset == 0.0f && collector_.ShaderType != RendererShaderType::Material)) { depthTexture = renderer->GetImpl()->GetProxyTexture(EffekseerRenderer::ProxyTextureType::White); } collector_.Textures[collector_.DepthIndex] = depthTexture; } // select shader Effekseer::MaterialRenderData* materialRenderData = param.BasicParameterPtr->MaterialRenderDataPtr; // materialRenderData = nullptr; Effekseer::MaterialRef material = nullptr; SHADER* shader_ = nullptr; bool renderDistortedBackground = false; if (collector_.ShaderType == EffekseerRenderer::RendererShaderType::Material && materialRenderData != nullptr && materialRenderData->MaterialIndex >= 0 && param.EffectPointer->GetMaterial(materialRenderData->MaterialIndex) != nullptr) { material = param.EffectPointer->GetMaterial(materialRenderData->MaterialIndex); if (material != nullptr && material->IsRefractionRequired) { if (renderPassInd == 0) { shader_ = (SHADER*)material->RefractionModelUserPtr; renderDistortedBackground = true; } else { shader_ = (SHADER*)material->ModelUserPtr; } } else { shader_ = (SHADER*)material->ModelUserPtr; } } else { if (collector_.DoRequireAdvancedRenderer()) { if (distortion) { shader_ = advanced_shader_distortion; } else if (collector_.ShaderType == EffekseerRenderer::RendererShaderType::AdvancedLit) { shader_ = advanced_shader_lit; } else { shader_ = advanced_shader_unlit; } } else { if (distortion) { shader_ = shader_distortion; } else if (collector_.ShaderType == EffekseerRenderer::RendererShaderType::Lit) { shader_ = shader_lit; } else { shader_ = shader_unlit; } } } // validate if (shader_ == nullptr) { return; } RenderStateBase::State& state = renderer->GetRenderState()->Push(); state.DepthTest = param.ZTest; state.DepthWrite = param.ZWrite; state.AlphaBlend = param.BasicParameterPtr->AlphaBlend; state.CullingType = param.Culling; // TODO : refactor in 1.7 if (renderer->GetExternalShaderSettings() != nullptr) { state.AlphaBlend = renderer->GetExternalShaderSettings()->Blend; } else if (renderer->GetRenderMode() == Effekseer::RenderMode::Wireframe) { state.AlphaBlend = ::Effekseer::AlphaBlendType::Opacity; } if (renderDistortedBackground) { state.AlphaBlend = ::Effekseer::AlphaBlendType::Blend; } renderer->BeginShader(shader_); for (int32_t i = 0; i < collector_.TextureCount; i++) { state.TextureFilterTypes[i] = collector_.TextureFilterTypes[i]; state.TextureWrapTypes[i] = collector_.TextureWrapTypes[i]; } renderer->SetTextures(shader_, collector_.Textures.data(), collector_.TextureCount); renderer->GetRenderState()->Update(distortion); VertexConstantBufferType* vcb = (VertexConstantBufferType*)shader_->GetVertexConstantBuffer(); float* cutomData1Ptr = nullptr; float* cutomData2Ptr = nullptr; if (materialRenderData != nullptr && material != nullptr) { StoreFileUniform( renderer, shader_, material, materialRenderData, param, renderPassInd, cutomData1Ptr, cutomData2Ptr); vcb->CameraMatrix = renderer->GetCameraProjectionMatrix(); } else { if (distortion) { StoreFixedUniforms(renderer, shader_, param); } else { StoreFixedUniforms(renderer, shader_, param); } } renderer->GetImpl()->CurrentRenderingUserData = param.UserData; renderer->GetImpl()->CurrentHandleUserData = userData; // Check time auto stTime0 = m_times[0] % model->GetFrameCount(); auto isTimeSame = true; for (auto t : m_times) { t = t % model->GetFrameCount(); if (t != stTime0) { isTimeSame = false; break; } } if (Instancing && isTimeSame) { //auto& imodel = model->InternalModels[stTime0]; // Invalid unless layout is set after buffer renderer->SetVertexBuffer(model->GetVertexBuffer(stTime0), sizeof(Effekseer::Model::Vertex)); int32_t indexPerFace = 3; if (renderer->GetRenderMode() == Effekseer::RenderMode::Wireframe) { renderer->SetIndexBuffer(model->GetWireIndexBuffer(stTime0)); indexPerFace = 6; } else { renderer->SetIndexBuffer(model->GetIndexBuffer(stTime0)); } renderer->SetLayout(shader_); for (size_t loop = 0; loop < m_matrixes.size();) { int32_t modelCount = Effekseer::Min(static_cast(m_matrixes.size()) - (int32_t)loop, InstanceCount); for (int32_t num = 0; num < modelCount; num++) { vcb->ModelMatrix[num] = m_matrixes[loop + num]; // DepthParameter ::Effekseer::SIMD::Mat44f modelMatrix = vcb->ModelMatrix[num]; if (param.EnableViewOffset) { ApplyViewOffset(modelMatrix, renderer->GetCameraMatrix(), m_viewOffsetDistance[loop + num]); } ApplyDepthParameters(modelMatrix, renderer->GetCameraFrontDirection(), renderer->GetCameraPosition(), param.DepthParameterPtr, param.IsRightHand); vcb->ModelMatrix[num] = ToStruct(modelMatrix); vcb->ModelUV[num][0] = m_uv[loop + num].X; vcb->ModelUV[num][1] = m_uv[loop + num].Y; vcb->ModelUV[num][2] = m_uv[loop + num].Width; vcb->ModelUV[num][3] = m_uv[loop + num].Height; vcb->SetModelAlphaUV( num, m_alphaUV[loop + num].X, m_alphaUV[loop + num].Y, m_alphaUV[loop + num].Width, m_alphaUV[loop + num].Height); vcb->SetModelUVDistortionUV(num, m_uvDistortionUV[loop + num].X, m_uvDistortionUV[loop + num].Y, m_uvDistortionUV[loop + num].Width, m_uvDistortionUV[loop + num].Height); vcb->SetModelBlendUV( num, m_blendUV[loop + num].X, m_blendUV[loop + num].Y, m_blendUV[loop + num].Width, m_blendUV[loop + num].Height); vcb->SetModelBlendAlphaUV(num, m_blendAlphaUV[loop + num].X, m_blendAlphaUV[loop + num].Y, m_blendAlphaUV[loop + num].Width, m_blendAlphaUV[loop + num].Height); vcb->SetModelBlendUVDistortionUV(num, m_blendUVDistortionUV[loop + num].X, m_blendUVDistortionUV[loop + num].Y, m_blendUVDistortionUV[loop + num].Width, m_blendUVDistortionUV[loop + num].Height); vcb->SetModelFlipbookIndexAndNextRate(num, m_flipbookIndexAndNextRate[loop + num]); vcb->SetModelAlphaThreshold(num, m_alphaThreshold[loop + num]); ColorToFloat4(m_colors[loop + num], vcb->ModelColor[num]); if (cutomData1Ptr != nullptr) { cutomData1Ptr[num * 4 + 0] = customData1_[loop + num][0]; cutomData1Ptr[num * 4 + 1] = customData1_[loop + num][1]; cutomData1Ptr[num * 4 + 2] = customData1_[loop + num][2]; cutomData1Ptr[num * 4 + 3] = customData1_[loop + num][3]; } if (cutomData2Ptr != nullptr) { cutomData2Ptr[num * 4 + 0] = customData2_[loop + num][0]; cutomData2Ptr[num * 4 + 1] = customData2_[loop + num][1]; cutomData2Ptr[num * 4 + 2] = customData2_[loop + num][2]; cutomData2Ptr[num * 4 + 3] = customData2_[loop + num][3]; } } shader_->SetConstantBuffer(); if (VertexType == ModelRendererVertexType::Instancing) { renderer->DrawPolygonInstanced(model->GetVertexCount(stTime0), model->GetFaceCount(stTime0) * indexPerFace, modelCount); } else { assert(0); } loop += modelCount; } } else { for (size_t loop = 0; loop < m_matrixes.size();) { auto stTime = m_times[loop] % model->GetFrameCount(); // auto& imodel = model->InternalModels[stTime]; // Invalid unless layout is set after buffer renderer->SetVertexBuffer(model->GetVertexBuffer(stTime), sizeof(Effekseer::Model::Vertex)); int32_t indexPerFace = 3; if (renderer->GetRenderMode() == Effekseer::RenderMode::Wireframe) { renderer->SetIndexBuffer(model->GetWireIndexBuffer(stTime)); indexPerFace = 6; } else { renderer->SetIndexBuffer(model->GetIndexBuffer(stTime)); } renderer->SetLayout(shader_); vcb->ModelMatrix[0] = m_matrixes[loop]; vcb->ModelUV[0][0] = m_uv[loop].X; vcb->ModelUV[0][1] = m_uv[loop].Y; vcb->ModelUV[0][2] = m_uv[loop].Width; vcb->ModelUV[0][3] = m_uv[loop].Height; vcb->SetModelAlphaUV(0, m_alphaUV[loop].X, m_alphaUV[loop].Y, m_alphaUV[loop].Width, m_alphaUV[loop].Height); vcb->SetModelUVDistortionUV( 0, m_uvDistortionUV[loop].X, m_uvDistortionUV[loop].Y, m_uvDistortionUV[loop].Width, m_uvDistortionUV[loop].Height); vcb->SetModelBlendUV(0, m_blendUV[loop].X, m_blendUV[loop].Y, m_blendUV[loop].Width, m_blendUV[loop].Height); vcb->SetModelBlendAlphaUV( 0, m_blendAlphaUV[loop].X, m_blendAlphaUV[loop].Y, m_blendAlphaUV[loop].Width, m_blendAlphaUV[loop].Height); vcb->SetModelBlendUVDistortionUV( 0, m_blendUVDistortionUV[loop].X, m_blendUVDistortionUV[loop].Y, m_blendUVDistortionUV[loop].Width, m_blendUVDistortionUV[loop].Height); vcb->SetModelFlipbookIndexAndNextRate(0, m_flipbookIndexAndNextRate[loop]); vcb->SetModelAlphaThreshold(0, m_alphaThreshold[loop]); // DepthParameters ::Effekseer::SIMD::Mat44f modelMatrix = vcb->ModelMatrix[0]; if (param.EnableViewOffset == true) { ApplyViewOffset(modelMatrix, renderer->GetCameraMatrix(), m_viewOffsetDistance[0]); } ApplyDepthParameters(modelMatrix, renderer->GetCameraFrontDirection(), renderer->GetCameraPosition(), param.DepthParameterPtr, param.IsRightHand); vcb->ModelMatrix[0] = ToStruct(modelMatrix); ColorToFloat4(m_colors[loop], vcb->ModelColor[0]); if (cutomData1Ptr != nullptr) { cutomData1Ptr[0] = customData1_[loop][0]; cutomData1Ptr[1] = customData1_[loop][1]; cutomData1Ptr[2] = customData1_[loop][2]; cutomData1Ptr[3] = customData1_[loop][3]; } if (cutomData2Ptr != nullptr) { cutomData2Ptr[0] = customData2_[loop][0]; cutomData2Ptr[1] = customData2_[loop][1]; cutomData2Ptr[2] = customData2_[loop][2]; cutomData2Ptr[3] = customData2_[loop][3]; } shader_->SetConstantBuffer(); renderer->DrawPolygon(model->GetVertexCount(stTime), model->GetFaceCount(stTime) * indexPerFace); loop += 1; } } renderer->EndShader(shader_); renderer->GetRenderState()->Pop(); } }; //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- } // namespace EffekseerRenderer //---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- #endif // __EFFEKSEERRENDERER_MODEL_RENDERER_H__