From 7100ed437fc4474281fcafefdc672133c79ef026 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Fri, 16 Mar 2018 17:41:01 -1000 Subject: [PATCH] macOS decal rendering support --- DataSpec/DNAMP1/DeafBabe.cpp | 2 +- DataSpec/DNAMP2/DeafBabe.cpp | 2 +- Runtime/Collision/CCollisionResponseData.cpp | 29 +- Runtime/Graphics/CBooRenderer.cpp | 3 +- Runtime/Graphics/CMakeLists.txt | 4 + Runtime/Graphics/Shaders/CDecalShaders.cpp | 44 ++ Runtime/Graphics/Shaders/CDecalShaders.hpp | 50 ++ .../Graphics/Shaders/CDecalShadersGLSL.cpp | 439 ++++++++++++++++++ .../Graphics/Shaders/CDecalShadersHLSL.cpp | 389 ++++++++++++++++ .../Graphics/Shaders/CDecalShadersMetal.cpp | 221 +++++++++ Runtime/MP1/CMFGame.cpp | 8 + Runtime/MP1/CMFGame.hpp | 1 + Runtime/Particle/CDecal.cpp | 268 ++++++++++- Runtime/Particle/CDecal.hpp | 67 +-- Runtime/Particle/CDecalDataFactory.cpp | 7 +- Runtime/Particle/CDecalDataFactory.hpp | 3 +- Runtime/Particle/CDecalDescription.hpp | 26 +- Runtime/Particle/CDecalManager.cpp | 79 +++- Runtime/Particle/CDecalManager.hpp | 11 +- Runtime/Particle/CElementGen.cpp | 32 +- Runtime/Particle/CParticleGlobals.hpp | 32 ++ Runtime/Weapon/CEnergyProjectile.cpp | 1 + 22 files changed, 1613 insertions(+), 105 deletions(-) create mode 100644 Runtime/Graphics/Shaders/CDecalShaders.cpp create mode 100644 Runtime/Graphics/Shaders/CDecalShaders.hpp create mode 100644 Runtime/Graphics/Shaders/CDecalShadersGLSL.cpp create mode 100644 Runtime/Graphics/Shaders/CDecalShadersHLSL.cpp create mode 100644 Runtime/Graphics/Shaders/CDecalShadersMetal.cpp diff --git a/DataSpec/DNAMP1/DeafBabe.cpp b/DataSpec/DNAMP1/DeafBabe.cpp index a69d3989b..2bc0ab6e1 100644 --- a/DataSpec/DNAMP1/DeafBabe.cpp +++ b/DataSpec/DNAMP1/DeafBabe.cpp @@ -51,7 +51,7 @@ void DeafBabe::BlenderInit(hecl::blender::PyOutStream& os) "bpy.types.Material.retro_half_pipe = bpy.props.BoolProperty(name='Retro: Half Pipe (H)')\n" "bpy.types.Material.retro_surface_mud = bpy.props.BoolProperty(name='Retro Surface: Mud')\n" "bpy.types.Material.retro_surface_glass = bpy.props.BoolProperty(name='Retro Surface: Glass')\n" - "bpy.types.Material.retro_surface_shield = bpy.props.BoolProperty(name='Retro Surface: Sheild')\n" + "bpy.types.Material.retro_surface_shield = bpy.props.BoolProperty(name='Retro Surface: Shield')\n" "bpy.types.Material.retro_surface_sand = bpy.props.BoolProperty(name='Retro Surface: Sand')\n" "bpy.types.Material.retro_projectile_passthrough = bpy.props.BoolProperty(name='Retro: Projectile Passthrough (P)')\n" "bpy.types.Material.retro_solid = bpy.props.BoolProperty(name='Retro: Solid (K)')\n" diff --git a/DataSpec/DNAMP2/DeafBabe.cpp b/DataSpec/DNAMP2/DeafBabe.cpp index 138b59f1e..72d6d98d5 100644 --- a/DataSpec/DNAMP2/DeafBabe.cpp +++ b/DataSpec/DNAMP2/DeafBabe.cpp @@ -53,7 +53,7 @@ void DeafBabe::BlenderInit(hecl::blender::PyOutStream& os) "bpy.types.Material.retro_unused4 = bpy.props.BoolProperty(description='Retro: Unused 4 (U)')\n" "bpy.types.Material.retro_surface_mud = bpy.props.BoolProperty(description='Retro Surface: Mud')\n" "bpy.types.Material.retro_surface_glass = bpy.props.BoolProperty(description='Retro Surface: Glass')\n" - "bpy.types.Material.retro_surface_shield = bpy.props.BoolProperty(description='Retro Surface: Sheild')\n" + "bpy.types.Material.retro_surface_shield = bpy.props.BoolProperty(description='Retro Surface: Shield')\n" "bpy.types.Material.retro_surface_sand = bpy.props.BoolProperty(description='Retro Surface: Sand')\n" "bpy.types.Material.retro_surface_moth_or_seed_organics = bpy.props.BoolProperty(description='Retro Surface: Moth/Seed Organics')\n" "bpy.types.Material.retro_surface_web = bpy.props.BoolProperty(description='Retro Surface: Web')\n" diff --git a/Runtime/Collision/CCollisionResponseData.cpp b/Runtime/Collision/CCollisionResponseData.cpp index 16a8c1229..57acc9088 100644 --- a/Runtime/Collision/CCollisionResponseData.cpp +++ b/Runtime/Collision/CCollisionResponseData.cpp @@ -182,6 +182,32 @@ CCollisionResponseData::CCollisionResponseData(CInputStream& in, CSimplePool* re const rstl::optional_object>& CCollisionResponseData::GetParticleDescription(EWeaponCollisionResponseTypes type) const { + if (x0_generators[u32(type)]) + return x0_generators[u32(type)]; + + bool foundType = false; + if (ResponseTypeIsEnemyNormal(type)) + { + type = EWeaponCollisionResponseTypes::EnemyNormal; + foundType = true; + } + else if (ResponseTypeIsEnemySpecial(type)) + { + type = EWeaponCollisionResponseTypes::EnemySpecial; + foundType = true; + } + else if (ResponseTypeIsEnemyShielded(type)) + { + type = EWeaponCollisionResponseTypes::EnemyShielded; + foundType = true; + } + + if (foundType && !x0_generators[u32(type)]) + type = EWeaponCollisionResponseTypes::EnemyNormal; + + if (!x0_generators[u32(type)] && type != EWeaponCollisionResponseTypes::None) + type = EWeaponCollisionResponseTypes::Default; + return x0_generators[u32(type)]; } @@ -210,9 +236,8 @@ s32 CCollisionResponseData::GetSoundEffectId(EWeaponCollisionResponseTypes type) EWeaponCollisionResponseTypes CCollisionResponseData::GetWorldCollisionResponseType(s32 id) { - if (id < 0 || id >= s32(EWeaponCollisionResponseTypes::Unknown32)) + if (id < 0 || id >= 32) return EWeaponCollisionResponseTypes::Default; - return skWorldMaterialTable[id]; } diff --git a/Runtime/Graphics/CBooRenderer.cpp b/Runtime/Graphics/CBooRenderer.cpp index b9313c81d..8e7a06495 100644 --- a/Runtime/Graphics/CBooRenderer.cpp +++ b/Runtime/Graphics/CBooRenderer.cpp @@ -1039,7 +1039,8 @@ void CBooRenderer::AddPlaneObject(const void*, const zeus::CAABox&, const zeus:: } -void CBooRenderer::AddDrawable(const void* obj, const zeus::CVector3f& pos, const zeus::CAABox& aabb, int mode, EDrawableSorting sorting) +void CBooRenderer::AddDrawable(const void* obj, const zeus::CVector3f& pos, const zeus::CAABox& aabb, + int mode, EDrawableSorting sorting) { if (sorting == EDrawableSorting::UnsortedCallback) xa8_drawableCallback(obj, xac_callbackContext, mode); diff --git a/Runtime/Graphics/CMakeLists.txt b/Runtime/Graphics/CMakeLists.txt index 4cce21cb9..bb64a4ceb 100644 --- a/Runtime/Graphics/CMakeLists.txt +++ b/Runtime/Graphics/CMakeLists.txt @@ -19,6 +19,7 @@ if(WIN32) Shaders/CScanLinesFilterHLSL.cpp Shaders/CRandomStaticFilterHLSL.cpp Shaders/CElementGenShadersHLSL.cpp + Shaders/CDecalShadersHLSL.cpp Shaders/CParticleSwooshShadersHLSL.cpp Shaders/CFluidPlaneShaderHLSL.cpp Shaders/CAABoxShaderHLSL.cpp @@ -44,6 +45,7 @@ elseif(BOO_HAS_METAL) Shaders/CScanLinesFilterMetal.cpp Shaders/CRandomStaticFilterMetal.cpp Shaders/CElementGenShadersMetal.cpp + Shaders/CDecalShadersMetal.cpp Shaders/CParticleSwooshShadersMetal.cpp Shaders/CFluidPlaneShaderMetal.cpp Shaders/CAABoxShaderMetal.cpp @@ -71,6 +73,7 @@ if(NOT WINDOWS_STORE) Shaders/CScanLinesFilterGLSL.cpp Shaders/CRandomStaticFilterGLSL.cpp Shaders/CElementGenShadersGLSL.cpp + Shaders/CDecalShadersGLSL.cpp Shaders/CParticleSwooshShadersGLSL.cpp Shaders/CFluidPlaneShaderGLSL.cpp Shaders/CAABoxShaderGLSL.cpp @@ -119,6 +122,7 @@ set(GRAPHICS_SOURCES Shaders/CScanLinesFilter.hpp Shaders/CScanLinesFilter.cpp Shaders/CRandomStaticFilter.hpp Shaders/CRandomStaticFilter.cpp Shaders/CElementGenShaders.hpp Shaders/CElementGenShaders.cpp + Shaders/CDecalShaders.hpp Shaders/CDecalShaders.cpp Shaders/CParticleSwooshShaders.hpp Shaders/CParticleSwooshShaders.cpp Shaders/CFluidPlaneShader.hpp Shaders/CFluidPlaneShader.cpp Shaders/CAABoxShader.hpp Shaders/CAABoxShader.cpp diff --git a/Runtime/Graphics/Shaders/CDecalShaders.cpp b/Runtime/Graphics/Shaders/CDecalShaders.cpp new file mode 100644 index 000000000..c59d5c4ac --- /dev/null +++ b/Runtime/Graphics/Shaders/CDecalShaders.cpp @@ -0,0 +1,44 @@ +#include "CDecalShaders.hpp" +#include "Particle/CDecal.hpp" + +namespace urde +{ + +boo::ObjToken CDecalShaders::m_texZTestNoZWrite; +boo::ObjToken CDecalShaders::m_texAdditiveZTest; +boo::ObjToken CDecalShaders::m_texRedToAlphaZTest; + +boo::ObjToken CDecalShaders::m_noTexZTestNoZWrite; +boo::ObjToken CDecalShaders::m_noTexAdditiveZTest; + +boo::ObjToken CDecalShaders::m_vtxFormatTex; +boo::ObjToken CDecalShaders::m_vtxFormatNoTex; + +void CDecalShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CQuadDecal& decal) +{ + boo::ObjToken regPipeline; + boo::ObjToken redToAlphaPipeline; + + if (decal.m_desc->x14_TEX) + { + if (decal.m_desc->x18_ADD) + regPipeline = m_texAdditiveZTest; + else + regPipeline = m_texZTestNoZWrite; + redToAlphaPipeline = m_texRedToAlphaZTest; + } + else + { + if (decal.m_desc->x18_ADD) + regPipeline = m_noTexAdditiveZTest; + else + regPipeline = m_noTexZTestNoZWrite; + } + + CDecalShaders shad(decal, regPipeline, redToAlphaPipeline); + TShader::BuildShaderDataBinding(ctx, shad); +} + +URDE_SPECIALIZE_SHADER(CDecalShaders) + +} diff --git a/Runtime/Graphics/Shaders/CDecalShaders.hpp b/Runtime/Graphics/Shaders/CDecalShaders.hpp new file mode 100644 index 000000000..9840c20cf --- /dev/null +++ b/Runtime/Graphics/Shaders/CDecalShaders.hpp @@ -0,0 +1,50 @@ +#ifndef __URDE_CDECALSHADERS_HPP__ +#define __URDE_CDECALSHADERS_HPP__ + +#include "TShader.hpp" +#include "Graphics/CGraphics.hpp" +#include "boo/graphicsdev/GL.hpp" +#include "boo/graphicsdev/D3D.hpp" +#include "boo/graphicsdev/Metal.hpp" +#include "boo/graphicsdev/Vulkan.hpp" + +namespace urde +{ +class CQuadDecal; + +class CDecalShaders +{ + friend struct OGLDecalDataBindingFactory; + friend struct VulkanDecalDataBindingFactory; + friend struct D3DDecalDataBindingFactory; + friend struct MetalDecalDataBindingFactory; + +private: + static boo::ObjToken m_texZTestNoZWrite; + static boo::ObjToken m_texAdditiveZTest; + static boo::ObjToken m_texRedToAlphaZTest; + + static boo::ObjToken m_noTexZTestNoZWrite; + static boo::ObjToken m_noTexAdditiveZTest; + + static boo::ObjToken m_vtxFormatTex; /* No OpenGL */ + static boo::ObjToken m_vtxFormatNoTex; /* No OpenGL */ + + CQuadDecal& m_decal; + boo::ObjToken m_regPipeline; + boo::ObjToken m_redToAlphaPipeline; + CDecalShaders(CQuadDecal& decal, + const boo::ObjToken& regPipeline, + const boo::ObjToken& redToAlphaPipeline) + : m_decal(decal), m_regPipeline(regPipeline), m_redToAlphaPipeline(redToAlphaPipeline) {} + +public: + static void BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CQuadDecal& decal); + + using _CLS = CDecalShaders; +#include "TShaderDecl.hpp" +}; + +} + +#endif // __URDE_CDECALSHADERS_HPP__ diff --git a/Runtime/Graphics/Shaders/CDecalShadersGLSL.cpp b/Runtime/Graphics/Shaders/CDecalShadersGLSL.cpp new file mode 100644 index 000000000..0bbc57090 --- /dev/null +++ b/Runtime/Graphics/Shaders/CDecalShadersGLSL.cpp @@ -0,0 +1,439 @@ +#include "CDecalShaders.hpp" +#include "Particle/CDecal.hpp" +#include "Graphics/CModel.hpp" + +namespace urde +{ + +static const char* VS_GLSL_TEX = +"#version 330\n" +BOO_GLSL_BINDING_HEAD +"layout(location=0) in vec4 posIn[4];\n" +"layout(location=4) in vec4 colorIn;\n" +"layout(location=5) in vec4 uvsIn[4];\n" +"\n" +"UBINDING0 uniform DecalUniform\n" +"{\n" +" mat4 mvp;\n" +" vec4 moduColor;\n" +"};\n" +"\n" +"struct VertToFrag\n" +"{\n" +" vec4 color;\n" +" vec2 uv;\n" +"};\n" +"\n" +"SBINDING(0) out VertToFrag vtf;\n" +"void main()\n" +"{\n" +" vtf.color = colorIn * moduColor;\n" +" vtf.uv = uvsIn[gl_VertexID].xy;\n" +" gl_Position = mvp * posIn[gl_VertexID];\n" +"}\n"; + +static const char* FS_GLSL_TEX = +"#version 330\n" +BOO_GLSL_BINDING_HEAD +"struct VertToFrag\n" +"{\n" +" vec4 color;\n" +" vec2 uv;\n" +"};\n" +"\n" +"SBINDING(0) in VertToFrag vtf;\n" +"layout(location=0) out vec4 colorOut;\n" +"TBINDING0 uniform sampler2D tex;\n" +"void main()\n" +"{\n" +" colorOut = vtf.color * texture(tex, vtf.uv);\n" +"}\n"; + +static const char* FS_GLSL_TEX_REDTOALPHA = +"#version 330\n" +BOO_GLSL_BINDING_HEAD +"struct VertToFrag\n" +"{\n" +" vec4 color;\n" +" vec2 uv;\n" +"};\n" +"\n" +"SBINDING(0) in VertToFrag vtf;\n" +"layout(location=0) out vec4 colorOut;\n" +"TBINDING0 uniform sampler2D tex;\n" +"void main()\n" +"{\n" +" colorOut = vtf.color;\n" +" colorOut.a = texture(tex, vtf.uv).r;\n" +"}\n"; + +static const char* VS_GLSL_NOTEX = +"#version 330\n" +BOO_GLSL_BINDING_HEAD +"layout(location=0) in vec4 posIn[4];\n" +"layout(location=4) in vec4 colorIn;\n" +"\n" +"UBINDING0 uniform DecalUniform\n" +"{\n" +" mat4 mvp;\n" +" vec4 moduColor;\n" +"};\n" +"\n" +"struct VertToFrag\n" +"{\n" +" vec4 color;\n" +"};\n" +"\n" +"SBINDING(0) out VertToFrag vtf;\n" +"void main()\n" +"{\n" +" vtf.color = colorIn * moduColor;\n" +" gl_Position = mvp * posIn[gl_VertexID];\n" +"}\n"; + +static const char* FS_GLSL_NOTEX = +"#version 330\n" +BOO_GLSL_BINDING_HEAD +"struct VertToFrag\n" +"{\n" +" vec4 color;\n" +"};\n" +"\n" +"SBINDING(0) in VertToFrag vtf;\n" +"layout(location=0) out vec4 colorOut;\n" +"void main()\n" +"{\n" +" colorOut = vtf.color;\n" +"}\n"; + +struct OGLDecalDataBindingFactory : TShader::IDataBindingFactory +{ + boo::ObjToken BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, + CDecalShaders& shaders) + { + CQuadDecal& decal = shaders.m_decal; + const SQuadDescr* desc = decal.m_desc; + + boo::ObjToken vtxFmt; + CUVElement* texr = desc->x14_TEX.get(); + int texCount = 0; + boo::ObjToken textures[1]; + + if (texr) + { + textures[0] = texr->GetValueTexture(0).GetObj()->GetBooTexture(); + texCount = 1; + if (decal.m_instBuf) + { + const boo::VertexElementDescriptor TexFmtTex[] = + { + {decal.m_instBuf.get(), nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0}, + {decal.m_instBuf.get(), nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1}, + {decal.m_instBuf.get(), nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2}, + {decal.m_instBuf.get(), nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3}, + {decal.m_instBuf.get(), nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced}, + {decal.m_instBuf.get(), nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 0}, + {decal.m_instBuf.get(), nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 1}, + {decal.m_instBuf.get(), nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 2}, + {decal.m_instBuf.get(), nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 3} + }; + vtxFmt = ctx.newVertexFormat(9, TexFmtTex); + } + } + else + { + if (decal.m_instBuf) + { + const boo::VertexElementDescriptor TexFmtNoTex[] = + { + {decal.m_instBuf.get(), nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0}, + {decal.m_instBuf.get(), nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1}, + {decal.m_instBuf.get(), nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2}, + {decal.m_instBuf.get(), nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3}, + {decal.m_instBuf.get(), nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced} + }; + vtxFmt = ctx.newVertexFormat(5, TexFmtNoTex); + } + } + + if (decal.m_instBuf) + { + boo::ObjToken uniforms[] = {decal.m_uniformBuf.get()}; + + if (shaders.m_regPipeline) + decal.m_normalDataBind = ctx.newShaderDataBinding(shaders.m_regPipeline, vtxFmt, nullptr, + decal.m_instBuf.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); + if (shaders.m_redToAlphaPipeline) + decal.m_redToAlphaDataBind = ctx.newShaderDataBinding(shaders.m_redToAlphaPipeline, vtxFmt, nullptr, + decal.m_instBuf.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); + } + + return nullptr; + } +}; + +static const char* UniNames[] = {"DecalUniform"}; +static const char* TexNames[] = {"tex"}; + +TShader::IDataBindingFactory* CDecalShaders::Initialize(boo::GLDataFactory::Context& ctx) +{ + m_texZTestNoZWrite = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, 1, TexNames, 1, UniNames, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + + m_texAdditiveZTest = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, 1, TexNames, 1, UniNames, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + + m_texRedToAlphaZTest = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX_REDTOALPHA, 1, TexNames, 1, UniNames, + boo::BlendFactor::One, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + + m_noTexZTestNoZWrite = ctx.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, 0, nullptr, 1, UniNames, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + + m_noTexAdditiveZTest = ctx.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, 0, nullptr, 1, UniNames, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + + return new struct OGLDecalDataBindingFactory; +} + +template <> +void CDecalShaders::Shutdown() +{ + m_texZTestNoZWrite.reset(); + m_texAdditiveZTest.reset(); + m_texRedToAlphaZTest.reset(); + + m_noTexZTestNoZWrite.reset(); + m_noTexAdditiveZTest.reset(); +} + +#if BOO_HAS_VULKAN +struct VulkanDecalDataBindingFactory : TShader::IDataBindingFactory +{ + boo::ObjToken + BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, + CElementGenShaders& shaders) + { + CElementGen& gen = shaders.m_gen; + CGenDescription* desc = gen.GetDesc(); + + CUVElement* texr = desc->x54_x40_TEXR.get(); + CUVElement* tind = desc->x58_x44_TIND.get(); + int texCount = 0; + boo::ObjToken textures[3]; + + if (texr) + { + textures[0] = texr->GetValueTexture(0).GetObj()->GetBooTexture(); + texCount = 1; + if (tind) + { + textures[1] = CGraphics::g_SpareTexture.get(); + textures[2] = tind->GetValueTexture(0).GetObj()->GetBooTexture(); + texCount = 3; + } + } + + if (gen.m_instBuf) + { + boo::ObjToken uniforms[] = {gen.m_uniformBuf.get()}; + + if (shaders.m_regPipeline) + gen.m_normalDataBind = ctx.newShaderDataBinding(shaders.m_regPipeline, nullptr, nullptr, + gen.m_instBuf.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); + if (shaders.m_regPipelineSub) + gen.m_normalSubDataBind = ctx.newShaderDataBinding(shaders.m_regPipelineSub, nullptr, nullptr, + gen.m_instBuf.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); + if (shaders.m_redToAlphaPipeline) + gen.m_redToAlphaDataBind = ctx.newShaderDataBinding(shaders.m_redToAlphaPipeline, nullptr, nullptr, + gen.m_instBuf.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); + if (shaders.m_redToAlphaPipelineSub) + gen.m_redToAlphaSubDataBind = ctx.newShaderDataBinding(shaders.m_redToAlphaPipelineSub, nullptr, nullptr, + gen.m_instBuf.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); + + } + + if (gen.m_instBufPmus) + { + boo::ObjToken uniforms[] = {gen.m_uniformBufPmus.get()}; + texCount = std::min(texCount, 1); + + if (shaders.m_regPipelinePmus) + gen.m_normalDataBindPmus = ctx.newShaderDataBinding(shaders.m_regPipelinePmus, nullptr, nullptr, + gen.m_instBufPmus.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); + if (shaders.m_redToAlphaPipelinePmus) + gen.m_redToAlphaDataBindPmus = ctx.newShaderDataBinding(shaders.m_redToAlphaPipelinePmus, nullptr, nullptr, + gen.m_instBufPmus.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); + } + + return nullptr; + } +}; + +TShader::IDataBindingFactory* CElementGenShaders::Initialize(boo::VulkanDataFactory::Context& ctx) +{ + static const boo::VertexElementDescriptor TexFmtTex[] = + { + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3}, + {nullptr, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 0}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 1}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 2}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 3} + }; + m_vtxFormatTex = ctx.newVertexFormat(9, TexFmtTex); + + static const boo::VertexElementDescriptor TexFmtNoTex[] = + { + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3}, + {nullptr, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced} + }; + m_vtxFormatNoTex = ctx.newVertexFormat(5, TexFmtNoTex); + + m_texZTestZWrite = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, true, + true, false, boo::CullMode::None); + m_texNoZTestZWrite = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::None, true, + true, false, boo::CullMode::None); + m_texZTestNoZWrite = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texNoZTestNoZWrite = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_texAdditiveZTest = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texAdditiveNoZTest = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_texRedToAlphaZTest = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX_REDTOALPHA, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texRedToAlphaNoZTest = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX_REDTOALPHA, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_texZTestNoZWriteSub = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texNoZTestNoZWriteSub = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_texRedToAlphaZTestSub = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX_REDTOALPHA, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texRedToAlphaNoZTestSub = ctx.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX_REDTOALPHA, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_indTexZWrite = ctx.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_INDTEX, m_vtxFormatIndTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, true, + true, false, boo::CullMode::None); + m_indTexNoZWrite = ctx.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_INDTEX, m_vtxFormatIndTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_indTexAdditive = ctx.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_INDTEX, m_vtxFormatIndTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::LEqual, true, + true, false, boo::CullMode::None); + + m_cindTexZWrite = ctx.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_CINDTEX, m_vtxFormatIndTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, true, + true, false, boo::CullMode::None); + m_cindTexNoZWrite = ctx.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_CINDTEX, m_vtxFormatIndTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_cindTexAdditive = ctx.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_CINDTEX, m_vtxFormatIndTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::LEqual, true, + true, false, boo::CullMode::None); + + m_noTexZTestZWrite = ctx.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, m_vtxFormatNoTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, true, + true, false, boo::CullMode::None); + m_noTexNoZTestZWrite = ctx.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, m_vtxFormatNoTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::None, true, + true, false, boo::CullMode::None); + m_noTexZTestNoZWrite = ctx.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, m_vtxFormatNoTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_noTexNoZTestNoZWrite = ctx.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, m_vtxFormatNoTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_noTexAdditiveZTest = ctx.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, m_vtxFormatNoTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_noTexAdditiveNoZTest = ctx.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, m_vtxFormatNoTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + return new struct VulkanDecalDataBindingFactory; +} + +template <> +void CElementGenShaders::Shutdown() +{ + m_vtxFormatTex.reset(); + m_vtxFormatNoTex.reset(); + + m_texZTestNoZWrite.reset(); + m_texAdditiveZTest.reset(); + m_texRedToAlphaZTest.reset(); + + m_noTexZTestNoZWrite.reset(); + m_noTexAdditiveZTest.reset(); +} +#endif + +} diff --git a/Runtime/Graphics/Shaders/CDecalShadersHLSL.cpp b/Runtime/Graphics/Shaders/CDecalShadersHLSL.cpp new file mode 100644 index 000000000..a954dd8fc --- /dev/null +++ b/Runtime/Graphics/Shaders/CDecalShadersHLSL.cpp @@ -0,0 +1,389 @@ +#include "CDecalShaders.hpp" +#include "Particle/CDecal.hpp" +#include "Graphics/CModel.hpp" + +namespace urde +{ + +static const char* VS_HLSL_TEX = +"struct VertData\n" +"{\n" +" float4 posIn[4] : POSITION;\n" +" float4 colorIn : COLOR;\n" +" float4 uvsIn[4] : UV;\n" +"};\n" +"\n" +"cbuffer DecalUniform : register(b0)\n" +"{\n" +" float4x4 mvp;\n" +" float4 moduColor;\n" +"};\n" +"\n" +"struct VertToFrag\n" +"{\n" +" float4 position : SV_Position;\n" +" float4 color : COLOR;\n" +" float2 uv : UV;\n" +"};\n" +"\n" +"VertToFrag main(in VertData v, in uint vertId : SV_VertexID)\n" +"{\n" +" VertToFrag vtf;\n" +" vtf.color = v.colorIn * moduColor;\n" +" vtf.uv = v.uvsIn[vertId].xy;\n" +" vtf.position = mul(mvp, v.posIn[vertId]);\n" +" return vtf;\n" +"}\n"; + +static const char* FS_HLSL_TEX = +"SamplerState samp : register(s0);\n" +"Texture2D tex0 : register(t0);\n" +"struct VertToFrag\n" +"{\n" +" float4 position : SV_Position;\n" +" float4 color : COLOR;\n" +" float2 uv : UV;\n" +"};\n" +"\n" +"float4 main(in VertToFrag vtf) : SV_Target0\n" +"{\n" +" return vtf.color * tex0.Sample(samp, vtf.uv);\n" +"}\n"; + +static const char* FS_HLSL_TEX_REDTOALPHA = +"SamplerState samp : register(s0);\n" +"Texture2D tex0 : register(t0);\n" +"struct VertToFrag\n" +"{\n" +" float4 position : SV_Position;\n" +" float4 color : COLOR;\n" +" float2 uv : UV;\n" +"};\n" +"\n" +"float4 main(in VertToFrag vtf) : SV_Target0\n" +"{\n" +" return float4(vtf.color.rgb, tex0.Sample(samp, vtf.uv).r);\n" +"}\n"; + +static const char* VS_HLSL_NOTEX = +"struct VertData\n" +"{\n" +" float4 posIn[4] : POSITION;\n" +" float4 colorIn : COLOR;\n" +"};\n" +"\n" +"cbuffer DecalUniform : register(b0)\n" +"{\n" +" float4x4 mvp;\n" +" float4 moduColor;\n" +"};\n" +"\n" +"struct VertToFrag\n" +"{\n" +" float4 position : SV_Position;\n" +" float4 color : COLOR;\n" +"};\n" +"\n" +"VertToFrag main(in VertData v, in uint vertId : SV_VertexID)\n" +"{\n" +" VertToFrag vtf;\n" +" vtf.color = v.colorIn * moduColor;\n" +" vtf.position = mul(mvp, v.posIn[vertId]);\n" +" return vtf;\n" +"}\n"; + +static const char* FS_HLSL_NOTEX = +"struct VertToFrag\n" +"{\n" +" float4 position : SV_Position;\n" +" float4 color : COLOR;\n" +"};\n" +"\n" +"float4 main(in VertToFrag vtf) : SV_Target0\n" +"{\n" +" return vtf.color;\n" +"}\n"; + +struct D3DElementDataBindingFactory : TShader::IDataBindingFactory +{ + boo::ObjToken + BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, + CElementGenShaders& shaders) + { + CElementGen& gen = shaders.m_gen; + CGenDescription* desc = gen.GetDesc(); + + CUVElement* texr = desc->x54_x40_TEXR.get(); + CUVElement* tind = desc->x58_x44_TIND.get(); + int texCount = 0; + boo::ObjToken textures[3]; + + if (texr) + { + textures[0] = texr->GetValueTexture(0).GetObj()->GetBooTexture(); + texCount = 1; + if (tind) + { + textures[1] = CGraphics::g_SpareTexture.get(); + textures[2] = tind->GetValueTexture(0).GetObj()->GetBooTexture(); + texCount = 3; + } + } + + if (gen.m_instBuf) + { + boo::ObjToken uniforms[] = {gen.m_uniformBuf.get()}; + + if (shaders.m_regPipeline) + gen.m_normalDataBind = ctx.newShaderDataBinding(shaders.m_regPipeline, nullptr, nullptr, + gen.m_instBuf.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, + nullptr, nullptr); + if (shaders.m_regPipelineSub) + gen.m_normalSubDataBind = ctx.newShaderDataBinding(shaders.m_regPipelineSub, nullptr, nullptr, + gen.m_instBuf.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, + nullptr, nullptr); + if (shaders.m_redToAlphaPipeline) + gen.m_redToAlphaDataBind = ctx.newShaderDataBinding(shaders.m_redToAlphaPipeline, nullptr, nullptr, + gen.m_instBuf.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, + nullptr, nullptr); + if (shaders.m_redToAlphaPipelineSub) + gen.m_redToAlphaSubDataBind = ctx.newShaderDataBinding(shaders.m_redToAlphaPipelineSub, nullptr, nullptr, + gen.m_instBuf.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, + nullptr, nullptr); + } + + if (gen.m_instBufPmus) + { + boo::ObjToken uniforms[] = {gen.m_uniformBufPmus.get()}; + texCount = std::min(texCount, 1); + + if (shaders.m_regPipelinePmus) + gen.m_normalDataBindPmus = ctx.newShaderDataBinding(shaders.m_regPipelinePmus, nullptr, nullptr, + gen.m_instBuf.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, + nullptr, nullptr); + if (shaders.m_redToAlphaPipelinePmus) + gen.m_redToAlphaDataBindPmus = ctx.newShaderDataBinding(shaders.m_redToAlphaPipelinePmus, nullptr, nullptr, + gen.m_instBuf.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, + nullptr, nullptr); + } + + return nullptr; + } +}; + +TShader::IDataBindingFactory* CElementGenShaders::Initialize(boo::ID3DDataFactory::Context& ctx) +{ + static const boo::VertexElementDescriptor TexFmtTex[] = + { + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3}, + {nullptr, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 0}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 1}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 2}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 3} + }; + m_vtxFormatTex = ctx.newVertexFormat(9, TexFmtTex); + + static const boo::VertexElementDescriptor TexFmtIndTex[] = + { + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3}, + {nullptr, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 0}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 1}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 2}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 3}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 4} + }; + m_vtxFormatIndTex = ctx.newVertexFormat(10, TexFmtIndTex); + + static const boo::VertexElementDescriptor TexFmtNoTex[] = + { + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3}, + {nullptr, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced} + }; + m_vtxFormatNoTex = ctx.newVertexFormat(5, TexFmtNoTex); + + m_texZTestZWrite = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, true, + true, false, boo::CullMode::None); + m_texNoZTestZWrite = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::None, true, + true, false, boo::CullMode::None); + m_texZTestNoZWrite = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texNoZTestNoZWrite = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_texAdditiveZTest = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texAdditiveNoZTest = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_texRedToAlphaZTest = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX_REDTOALPHA, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texRedToAlphaNoZTest = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX_REDTOALPHA, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_texZTestNoZWriteSub = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texNoZTestNoZWriteSub = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_texRedToAlphaZTestSub = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX_REDTOALPHA, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_texRedToAlphaNoZTestSub = ctx.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX_REDTOALPHA, nullptr, nullptr, + nullptr, m_vtxFormatTex, + boo::BlendFactor::Subtract, boo::BlendFactor::Subtract, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_indTexZWrite = ctx.newShaderPipeline(VS_HLSL_INDTEX, FS_HLSL_INDTEX, nullptr, nullptr, + nullptr, m_vtxFormatIndTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::None, true, + true, false, boo::CullMode::None); + m_indTexNoZWrite = ctx.newShaderPipeline(VS_HLSL_INDTEX, FS_HLSL_INDTEX, nullptr, nullptr, + nullptr, m_vtxFormatIndTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + m_indTexAdditive = ctx.newShaderPipeline(VS_HLSL_INDTEX, FS_HLSL_INDTEX, nullptr, nullptr, + nullptr, m_vtxFormatIndTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::None, true, + true, false, boo::CullMode::None); + + m_cindTexZWrite = ctx.newShaderPipeline(VS_HLSL_INDTEX, FS_HLSL_CINDTEX, nullptr, nullptr, + nullptr, m_vtxFormatIndTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::None, true, + true, false, boo::CullMode::None); + m_cindTexNoZWrite = ctx.newShaderPipeline(VS_HLSL_INDTEX, FS_HLSL_CINDTEX, nullptr, nullptr, + nullptr, m_vtxFormatIndTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + m_cindTexAdditive = ctx.newShaderPipeline(VS_HLSL_INDTEX, FS_HLSL_CINDTEX, nullptr, nullptr, + nullptr, m_vtxFormatIndTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::None, true, + true, false, boo::CullMode::None); + + m_noTexZTestZWrite = ctx.newShaderPipeline(VS_HLSL_NOTEX, FS_HLSL_NOTEX, nullptr, nullptr, + nullptr, m_vtxFormatNoTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, true, + true, false, boo::CullMode::None); + m_noTexNoZTestZWrite = ctx.newShaderPipeline(VS_HLSL_NOTEX, FS_HLSL_NOTEX, nullptr, nullptr, + nullptr, m_vtxFormatNoTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::None, true, + true, false, boo::CullMode::None); + m_noTexZTestNoZWrite = ctx.newShaderPipeline(VS_HLSL_NOTEX, FS_HLSL_NOTEX, nullptr, nullptr, + nullptr, m_vtxFormatNoTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, + true, false, boo::CullMode::None); + m_noTexNoZTestNoZWrite = ctx.newShaderPipeline(VS_HLSL_NOTEX, FS_HLSL_NOTEX, nullptr, nullptr, + nullptr, m_vtxFormatNoTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::None, false, + true, false, boo::CullMode::None); + + m_noTexAdditiveZTest = ctx.newShaderPipeline(VS_HLSL_NOTEX, FS_HLSL_NOTEX, nullptr, nullptr, + nullptr, m_vtxFormatNoTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::LEqual, true, + true, false, boo::CullMode::None); + m_noTexAdditiveNoZTest = ctx.newShaderPipeline(VS_HLSL_NOTEX, FS_HLSL_NOTEX, nullptr, nullptr, + nullptr, m_vtxFormatNoTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::None, true, + true, false, boo::CullMode::None); + + return new struct D3DElementDataBindingFactory; +} + +template <> +void CElementGenShaders::Shutdown() +{ + m_vtxFormatTex.reset(); + m_vtxFormatIndTex.reset(); + m_vtxFormatNoTex.reset(); + + m_texZTestZWrite.reset(); + m_texNoZTestZWrite.reset(); + m_texZTestNoZWrite.reset(); + m_texNoZTestNoZWrite.reset(); + m_texAdditiveZTest.reset(); + m_texAdditiveNoZTest.reset(); + m_texRedToAlphaZTest.reset(); + m_texRedToAlphaNoZTest.reset(); + m_texZTestNoZWriteSub.reset(); + m_texNoZTestNoZWriteSub.reset(); + m_texRedToAlphaZTestSub.reset(); + m_texRedToAlphaNoZTestSub.reset(); + + m_indTexZWrite.reset(); + m_indTexNoZWrite.reset(); + m_indTexAdditive.reset(); + + m_cindTexZWrite.reset(); + m_cindTexNoZWrite.reset(); + m_cindTexAdditive.reset(); + + m_noTexZTestZWrite.reset(); + m_noTexNoZTestZWrite.reset(); + m_noTexZTestNoZWrite.reset(); + m_noTexNoZTestNoZWrite.reset(); + m_noTexAdditiveZTest.reset(); + m_noTexAdditiveNoZTest.reset(); +} + +} diff --git a/Runtime/Graphics/Shaders/CDecalShadersMetal.cpp b/Runtime/Graphics/Shaders/CDecalShadersMetal.cpp new file mode 100644 index 000000000..160b08258 --- /dev/null +++ b/Runtime/Graphics/Shaders/CDecalShadersMetal.cpp @@ -0,0 +1,221 @@ +#include "CDecalShaders.hpp" +#include "Particle/CDecal.hpp" + +namespace urde +{ + +static const char* VS_METAL_TEX = +"#include \n" +"using namespace metal;\n" +"struct VertData\n" +"{\n" +" float4 posIn[4];\n" +" float4 colorIn;\n" +" float4 uvsIn[4];\n" +"};\n" +"\n" +"struct DecalUniform\n" +"{\n" +" float4x4 mvp;\n" +" float4 moduColor;\n" +"};\n" +"\n" +"struct VertToFrag\n" +"{\n" +" float4 position [[ position ]];\n" +" float4 color;\n" +" float2 uv;\n" +"};\n" +"\n" +"vertex VertToFrag vmain(constant VertData* va [[ buffer(1) ]],\n" +" uint vertId [[ vertex_id ]], uint instId [[ instance_id ]],\n" +" constant DecalUniform& decal [[ buffer(2) ]])\n" +"{\n" +" VertToFrag vtf;\n" +" constant VertData& v = va[instId];\n" +" vtf.color = v.colorIn * decal.moduColor;\n" +" vtf.uv = v.uvsIn[vertId].xy;\n" +" vtf.position = decal.mvp * v.posIn[vertId];\n" +" return vtf;\n" +"}\n"; + +static const char* FS_METAL_TEX = +"#include \n" +"using namespace metal;\n" +"struct VertToFrag\n" +"{\n" +" float4 position [[ position ]];\n" +" float4 color;\n" +" float2 uv;\n" +"};\n" +"\n" +"fragment float4 fmain(VertToFrag vtf [[ stage_in ]],\n" +" sampler samp [[ sampler(0) ]],\n" +" texture2d tex0 [[ texture(0) ]])\n" +"{\n" +" return vtf.color * tex0.sample(samp, vtf.uv);\n" +"}\n"; + +static const char* FS_METAL_TEX_REDTOALPHA = +"#include \n" +"using namespace metal;\n" +"struct VertToFrag\n" +"{\n" +" float4 position [[ position ]];\n" +" float4 color;\n" +" float2 uv;\n" +"};\n" +"\n" +"fragment float4 fmain(VertToFrag vtf [[ stage_in ]],\n" +" sampler samp [[ sampler(0) ]],\n" +" texture2d tex0 [[ texture(0) ]])\n" +"{\n" +" return float4(vtf.color.rgb, tex0.sample(samp, vtf.uv).r);\n" +"}\n"; + +static const char* VS_METAL_NOTEX = +"#include \n" +"using namespace metal;\n" +"struct VertData\n" +"{\n" +" float4 posIn[4];\n" +" float4 colorIn;\n" +"};\n" +"\n" +"struct DecalUniform\n" +"{\n" +" float4x4 mvp;\n" +" float4 moduColor;\n" +"};\n" +"\n" +"struct VertToFrag\n" +"{\n" +" float4 position [[ position ]];\n" +" float4 color;\n" +"};\n" +"\n" +"vertex VertToFrag vmain(constant VertData* va [[ buffer(1) ]],\n" +" uint vertId [[ vertex_id ]], uint instId [[ instance_id ]],\n" +" constant DecalUniform& decal [[ buffer(2) ]])\n" +"{\n" +" VertToFrag vtf;\n" +" constant VertData& v = va[instId];\n" +" vtf.color = v.colorIn * decal.moduColor;\n" +" vtf.position = decal.mvp * v.posIn[vertId];\n" +" return vtf;\n" +"}\n"; + +static const char* FS_METAL_NOTEX = +"#include \n" +"using namespace metal;\n" +"struct VertToFrag\n" +"{\n" +" float4 position [[ position ]];\n" +" float4 color;\n" +"};\n" +"\n" +"fragment float4 fmain(VertToFrag vtf [[ stage_in ]])\n" +"{\n" +" return vtf.color;\n" +"}\n"; + +struct MetalDecalDataBindingFactory : TShader::IDataBindingFactory +{ + boo::ObjToken BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, + CDecalShaders& shader) + { + CQuadDecal& decal = shader.m_decal; + const SQuadDescr* desc = decal.m_desc; + + CUVElement* texr = desc->x14_TEX.get(); + int texCount = 0; + boo::ObjToken textures[1]; + + if (texr) + { + textures[0] = texr->GetValueTexture(0).GetObj()->GetBooTexture(); + texCount = 1; + } + + if (decal.m_instBuf) + { + boo::ObjToken uniforms[] = {decal.m_uniformBuf.get()}; + + if (shader.m_regPipeline) + decal.m_normalDataBind = ctx.newShaderDataBinding(shader.m_regPipeline, nullptr, nullptr, + decal.m_instBuf.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); + if (shader.m_redToAlphaPipeline) + decal.m_redToAlphaDataBind = ctx.newShaderDataBinding(shader.m_redToAlphaPipeline, nullptr, nullptr, + decal.m_instBuf.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); + } + + return {}; + } +}; + +TShader::IDataBindingFactory* CDecalShaders::Initialize(boo::MetalDataFactory::Context& ctx) +{ + static const boo::VertexElementDescriptor TexFmtTex[] = + { + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3}, + {nullptr, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 0}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 1}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 2}, + {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 3} + }; + m_vtxFormatTex = ctx.newVertexFormat(9, TexFmtTex); + + static const boo::VertexElementDescriptor TexFmtNoTex[] = + { + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2}, + {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3}, + {nullptr, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced} + }; + m_vtxFormatNoTex = ctx.newVertexFormat(5, TexFmtNoTex); + + m_texZTestNoZWrite = ctx.newShaderPipeline(VS_METAL_TEX, FS_METAL_TEX, nullptr, nullptr, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, boo::CullMode::None); + + m_texAdditiveZTest = ctx.newShaderPipeline(VS_METAL_TEX, FS_METAL_TEX, nullptr, nullptr, m_vtxFormatTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, boo::CullMode::None); + + m_texRedToAlphaZTest = ctx.newShaderPipeline(VS_METAL_TEX, FS_METAL_TEX_REDTOALPHA, nullptr, nullptr, m_vtxFormatTex, + boo::BlendFactor::One, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, true, boo::CullMode::None); + + m_noTexZTestNoZWrite = ctx.newShaderPipeline(VS_METAL_NOTEX, FS_METAL_NOTEX, nullptr, nullptr, m_vtxFormatNoTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, boo::CullMode::None); + + m_noTexAdditiveZTest = ctx.newShaderPipeline(VS_METAL_NOTEX, FS_METAL_NOTEX, nullptr, nullptr, m_vtxFormatNoTex, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::One, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, boo::CullMode::None); + + return new struct MetalDecalDataBindingFactory; +} + +template <> +void CDecalShaders::Shutdown() +{ + m_texZTestNoZWrite.reset(); + m_texAdditiveZTest.reset(); + m_texRedToAlphaZTest.reset(); + + m_noTexZTestNoZWrite.reset(); + m_noTexAdditiveZTest.reset(); + + m_vtxFormatTex.reset(); + m_vtxFormatNoTex.reset(); +} + +} diff --git a/Runtime/MP1/CMFGame.cpp b/Runtime/MP1/CMFGame.cpp index 1b985f56d..25ca92cc0 100644 --- a/Runtime/MP1/CMFGame.cpp +++ b/Runtime/MP1/CMFGame.cpp @@ -19,6 +19,14 @@ CMFGame::CMFGame(const std::weak_ptr& stateMgr, const std::weak_p static_cast(*g_Main).SetMFGameBuilt(true); } +CMFGame::~CMFGame() +{ + CMain& main = static_cast(*g_Main); + main.SetMFGameBuilt(false); + main.SetScreenFading(false); + CDecalManager::Reinitialize(); +} + CIOWin::EMessageReturn CMFGame::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { switch (msg.GetType()) diff --git a/Runtime/MP1/CMFGame.hpp b/Runtime/MP1/CMFGame.hpp index 88ff9fe7c..69dc2b337 100644 --- a/Runtime/MP1/CMFGame.hpp +++ b/Runtime/MP1/CMFGame.hpp @@ -50,6 +50,7 @@ class CMFGame : public CMFGameBase public: CMFGame(const std::weak_ptr& stateMgr, const std::weak_ptr& guiMgr, const CArchitectureQueue&); + ~CMFGame(); CIOWin::EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue); void Touch(); void Draw() const; diff --git a/Runtime/Particle/CDecal.cpp b/Runtime/Particle/CDecal.cpp index d482380bb..40402c42f 100644 --- a/Runtime/Particle/CDecal.cpp +++ b/Runtime/Particle/CDecal.cpp @@ -1,38 +1,56 @@ #include "CDecal.hpp" +#include "CParticleGlobals.hpp" +#include "Graphics/Shaders/CDecalShaders.hpp" +#include "Graphics/CModel.hpp" namespace urde { CRandom16 CDecal::sDecalRandom(99); -bool CDecal::sMoveRedToAphaBuffer = false; +bool CDecal::sMoveRedToAlphaBuffer = false; CDecal::CDecal(const TToken& desc, const zeus::CTransform& xf) - : x0_description(desc), - xc_transform(xf), - x3c_decalQuad1(0, 0.f), - x48_decalQuad2(0, 0.f) +: x0_description(desc), + xc_transform(xf) { CGlobalRandom gr(sDecalRandom); - x5c_31_quad1Invalid = InitQuad(x3c_decalQuad1, x0_description.GetObj()->x0_Quad); - x5c_30_quad2Invalid = InitQuad(x48_decalQuad2, x0_description.GetObj()->x1c_Quad); + CDecalDescription& desco = *x0_description; + x5c_31_quad1Invalid = InitQuad(x3c_decalQuads[0], desco.x0_Quads[0]); + x5c_30_quad2Invalid = InitQuad(x3c_decalQuads[1], desco.x0_Quads[1]); CDecalDescription* d = x0_description.GetObj(); if (d->x38_DMDL) { if (d->x48_DLFT) - d->x48_DLFT->GetValue(0, x54_lifetime); + d->x48_DLFT->GetValue(0, x54_modelLifetime); else - x54_lifetime = 0x7FFFFF; + x54_modelLifetime = 0x7FFFFF; if (d->x50_DMRT) d->x50_DMRT->GetValue(0, x60_rotation); } else x5c_29_modelInvalid = true; + + CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) + { + for (int i=0 ; i<2 ; ++i) + { + CQuadDecal& decal = x3c_decalQuads[i]; + if (decal.m_desc->x14_TEX) + decal.m_instBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(SParticleInstanceTex), 1); + else + decal.m_instBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(SParticleInstanceNoTex), 1); + decal.m_uniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1); + CDecalShaders::BuildShaderDataBinding(ctx, decal); + } + return true; + }); } -bool CDecal::InitQuad(CDecal::CQuadDecal& quad, const CDecalDescription::SQuadDescr& desc) +bool CDecal::InitQuad(CQuadDecal& quad, const SQuadDescr& desc) { + quad.m_desc = &desc; if (desc.x14_TEX) { if (desc.x0_LFT) @@ -70,11 +88,237 @@ void CDecal::SetGlobalSeed(u16 seed) void CDecal::SetMoveRedToAlphaBuffer(bool move) { - sMoveRedToAphaBuffer = move; + sMoveRedToAlphaBuffer = move; +} + +void CDecal::RenderQuad(CQuadDecal& decal, const SQuadDescr& desc) const +{ + zeus::CColor color = zeus::CColor::skWhite; + float size = 1.f; + zeus::CVector3f offset; + if (CColorElement* clr = desc.x10_CLR.get()) + clr->GetValue(x58_frameIdx, color); + if (CRealElement* sze = desc.x4_SZE.get()) + { + sze->GetValue(x58_frameIdx, size); + size *= 0.5f; + } + if (CRealElement* rot = desc.x8_ROT.get()) + rot->GetValue(x58_frameIdx, decal.x8_rotation); + if (CVectorElement* off = desc.xc_OFF.get()) + { + off->GetValue(x58_frameIdx, offset); + offset.y = 0.f; + } + zeus::CTransform modXf = xc_transform; + modXf.origin += offset; + CGraphics::SetModelMatrix(modXf); + + SParticleUniforms uniformData = + { + CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(), + {1.f, 1.f, 1.f, 1.f} + }; + decal.m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms)); + + bool redToAlpha = sMoveRedToAlphaBuffer && desc.x18_ADD && desc.x14_TEX; + + SUVElementSet uvSet = {0.f, 1.f, 0.f, 1.f}; + if (CUVElement* tex = desc.x14_TEX.get()) + { + TLockedToken texObj = tex->GetValueTexture(x58_frameIdx); + if (!texObj.IsLoaded()) + return; + tex->GetValueUV(x58_frameIdx, uvSet); + if (redToAlpha) + CGraphics::SetShaderDataBinding(decal.m_redToAlphaDataBind); + else + CGraphics::SetShaderDataBinding(decal.m_normalDataBind); + + g_instTexData.clear(); + g_instTexData.reserve(1); + + g_instTexData.emplace_back(); + SParticleInstanceTex& inst = g_instTexData.back(); + if (decal.x8_rotation == 0.f) + { + inst.pos[0] = zeus::CVector3f(-size, 0.001f, size); + inst.pos[1] = zeus::CVector3f(size, 0.001f, size); + inst.pos[2] = zeus::CVector3f(-size, 0.001f, -size); + inst.pos[3] = zeus::CVector3f(size, 0.001f, -size); + } + else + { + float ang = zeus::degToRad(decal.x8_rotation); + float sinSize = std::sin(ang) * size; + float cosSize = std::cos(ang) * size; + inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 0.001f, cosSize + sinSize); + inst.pos[1] = zeus::CVector3f(cosSize + sinSize, 0.001f, cosSize - sinSize); + inst.pos[2] = zeus::CVector3f(-(cosSize + sinSize), 0.001f, -(cosSize - sinSize)); + inst.pos[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize); + } + inst.color = color; + inst.uvs[0] = zeus::CVector2f(uvSet.xMin, uvSet.yMin); + inst.uvs[1] = zeus::CVector2f(uvSet.xMax, uvSet.yMin); + inst.uvs[2] = zeus::CVector2f(uvSet.xMin, uvSet.yMax); + inst.uvs[3] = zeus::CVector2f(uvSet.xMax, uvSet.yMax); + + decal.m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex)); + CGraphics::DrawInstances(0, 4, g_instTexData.size()); + } + else + { + g_instNoTexData.clear(); + g_instNoTexData.reserve(1); + + g_instNoTexData.emplace_back(); + SParticleInstanceNoTex& inst = g_instNoTexData.back(); + if (decal.x8_rotation == 0.f) + { + inst.pos[0] = zeus::CVector3f(-size, 0.001f, size); + inst.pos[1] = zeus::CVector3f(size, 0.001f, size); + inst.pos[2] = zeus::CVector3f(-size, 0.001f, -size); + inst.pos[3] = zeus::CVector3f(size, 0.001f, -size); + } + else + { + float ang = zeus::degToRad(decal.x8_rotation); + float sinSize = std::sin(ang) * size; + float cosSize = std::cos(ang) * size; + inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 0.001f, cosSize + sinSize); + inst.pos[1] = zeus::CVector3f(cosSize + sinSize, 0.001f, cosSize - sinSize); + inst.pos[2] = zeus::CVector3f(-(cosSize + sinSize), 0.001f, -(cosSize - sinSize)); + inst.pos[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize); + } + inst.color = color; + + decal.m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex)); + CGraphics::DrawInstances(0, 4, g_instNoTexData.size()); + } +} + +void CDecal::RenderMdl() const +{ + const CDecalDescription& desc = *x0_description; + zeus::CColor color = zeus::CColor::skWhite; + zeus::CVector3f dmop; + zeus::CTransform rotXf; + + if (!desc.x5c_25_DMOO) + rotXf = xc_transform.getRotation(); + + bool dmrtIsConst = false; + if (CVectorElement* dmrt = desc.x50_DMRT.get()) + dmrtIsConst = dmrt->IsFastConstant(); + + zeus::CTransform dmrtXf; + if (dmrtIsConst) + { + desc.x50_DMRT->GetValue(x58_frameIdx, const_cast(x60_rotation)); + dmrtXf = zeus::CTransform::RotateZ(zeus::degToRad(x60_rotation.z)); + dmrtXf.rotateLocalY(zeus::degToRad(x60_rotation.y)); + dmrtXf.rotateLocalX(zeus::degToRad(x60_rotation.x)); + } + + dmrtXf = rotXf * dmrtXf; + + if (CVectorElement* dmopo = desc.x4c_DMOP.get()) + dmopo->GetValue(x58_frameIdx, dmop); + + zeus::CTransform worldXf = zeus::CTransform::Translate(rotXf * dmop + xc_transform.origin); + + if (dmrtIsConst) + { + worldXf = worldXf * dmrtXf; + } + else + { + if (CVectorElement* dmrt = desc.x50_DMRT.get()) + { + zeus::CVector3f dmrtVec; + dmrt->GetValue(x58_frameIdx, dmrtVec); + dmrtXf = zeus::CTransform::RotateZ(zeus::degToRad(dmrtVec.z)); + dmrtXf.rotateLocalY(zeus::degToRad(dmrtVec.y)); + dmrtXf.rotateLocalX(zeus::degToRad(dmrtVec.x)); + worldXf = worldXf * rotXf * dmrtXf; + } + else + { + worldXf = worldXf * dmrtXf; + } + } + + if (CVectorElement* dmsc = desc.x54_DMSC.get()) + { + zeus::CVector3f dmscVec; + dmsc->GetValue(x58_frameIdx, dmscVec); + worldXf = worldXf * zeus::CTransform::Scale(dmscVec); + } + + if (CColorElement* dmcl = desc.x58_DMCL.get()) + dmcl->GetValue(x58_frameIdx, color); + + CGraphics::SetModelMatrix(worldXf); + + if (desc.x5c_24_DMAB) + { + CModelFlags flags(7, 0, 1, color); + desc.x38_DMDL.m_token->Draw(flags); + } + else + { + if (color.a == 1.f) + { + CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); + desc.x38_DMDL.m_token->Draw(flags); + } + else + { + CModelFlags flags(5, 0, 1, color); + desc.x38_DMDL.m_token->Draw(flags); + } + } } void CDecal::Render() const { + CGlobalRandom gr(sDecalRandom); + if (x5c_29_modelInvalid && x5c_30_quad2Invalid && x5c_31_quad1Invalid) + return; + + CGraphics::DisableAllLights(); + CParticleGlobals::SetEmitterTime(x58_frameIdx); + + const CDecalDescription& desc = *x0_description; + if (desc.x0_Quads[0].x14_TEX && !x5c_31_quad1Invalid) + { + CParticleGlobals::SetParticleLifetime(x3c_decalQuads[0].x4_lifetime); + CParticleGlobals::UpdateParticleLifetimeTweenValues(x58_frameIdx); + RenderQuad(const_cast(x3c_decalQuads[0]), desc.x0_Quads[0]); + } + if (desc.x0_Quads[1].x14_TEX && !x5c_30_quad2Invalid) + { + CParticleGlobals::SetParticleLifetime(x3c_decalQuads[1].x4_lifetime); + CParticleGlobals::UpdateParticleLifetimeTweenValues(x58_frameIdx); + RenderQuad(const_cast(x3c_decalQuads[1]), desc.x0_Quads[1]); + } + if (desc.x38_DMDL && !x5c_29_modelInvalid) + { + CParticleGlobals::SetParticleLifetime(x54_modelLifetime); + CParticleGlobals::UpdateParticleLifetimeTweenValues(x58_frameIdx); + RenderMdl(); + } +} + +void CDecal::Update(float dt) +{ + if (x58_frameIdx >= x3c_decalQuads[0].x4_lifetime) + x5c_31_quad1Invalid = true; + if (x58_frameIdx >= x3c_decalQuads[1].x4_lifetime) + x5c_30_quad2Invalid = true; + if (x58_frameIdx >= x54_modelLifetime) + x5c_29_modelInvalid = true; + ++x58_frameIdx; +} } -} diff --git a/Runtime/Particle/CDecal.hpp b/Runtime/Particle/CDecal.hpp index f8117ec3b..3bc8724ac 100644 --- a/Runtime/Particle/CDecal.hpp +++ b/Runtime/Particle/CDecal.hpp @@ -9,38 +9,44 @@ namespace urde { +struct SQuadDescr; +struct CQuadDecal +{ + union + { + struct + { + bool x0_24_invalid : 1; + }; + u32 _dummy = 0; + }; + s32 x4_lifetime = 0; + float x8_rotation = 0.f; + const SQuadDescr* m_desc = nullptr; + CQuadDecal() = default; + CQuadDecal(s32 i, float f) + : x4_lifetime(i), + x8_rotation(f) + { + x0_24_invalid = true; + } + + boo::ObjToken m_instBuf; + boo::ObjToken m_uniformBuf; + boo::ObjToken m_normalDataBind; + boo::ObjToken m_redToAlphaDataBind; +}; + class CDecal { friend class CDecalManager; -public: - struct CQuadDecal - { - union - { - struct - { - bool x0_24_invalid : 1; - }; - u32 _dummy = 0; - }; - s32 x4_lifetime = 0; - float x8_rotation = 0.f; - CQuadDecal(s32 i, float f) - : x4_lifetime(i), - x8_rotation(f) - { - x0_24_invalid = true; - } - }; -private: - static bool sMoveRedToAphaBuffer; + static bool sMoveRedToAlphaBuffer; static CRandom16 sDecalRandom; TLockedToken x0_description; zeus::CTransform xc_transform; - CQuadDecal x3c_decalQuad1; - CQuadDecal x48_decalQuad2; - s32 x54_lifetime = 0; + CQuadDecal x3c_decalQuads[2]; + s32 x54_modelLifetime = 0; s32 x58_frameIdx = 0; union { @@ -53,16 +59,13 @@ private: u32 x5c_dummy = 0; }; zeus::CVector3f x60_rotation; - bool InitQuad(CQuadDecal&, const CDecalDescription::SQuadDescr&); + bool InitQuad(CQuadDecal& quad, const SQuadDescr& desc); public: - CDecal(const TToken&, const zeus::CTransform&); - bool IsDone() const; - void RenderQuad(CQuadDecal&, const CDecalDescription::SQuadDescr&) const; + CDecal(const TToken& desc, const zeus::CTransform& xf); + void RenderQuad(CQuadDecal& decal, const SQuadDescr& desc) const; void RenderMdl() const; void Render() const; - void ProcessQuad(CQuadDecal&, const CDecalDescription::SQuadDescr&, s32) const; - void Update(float); - void CheckTime(s32, s32); + void Update(float dt); static void SetGlobalSeed(u16); static void SetMoveRedToAlphaBuffer(bool); diff --git a/Runtime/Particle/CDecalDataFactory.cpp b/Runtime/Particle/CDecalDataFactory.cpp index feed9f12d..0c9273171 100644 --- a/Runtime/Particle/CDecalDataFactory.cpp +++ b/Runtime/Particle/CDecalDataFactory.cpp @@ -58,9 +58,9 @@ bool CDecalDataFactory::CreateDPSM(CDecalDescription* desc, CInputStream& in, CS case SBIG('2TEX'): case SBIG('2ADD'): if (loadFirstDesc) - GetQuadDecalInfo(in, resPool, clsId, desc->x0_Quad); + GetQuadDecalInfo(in, resPool, clsId, desc->x0_Quads[0]); else - GetQuadDecalInfo(in, resPool, clsId, desc->x1c_Quad); + GetQuadDecalInfo(in, resPool, clsId, desc->x0_Quads[1]); break; case SBIG('DMDL'): @@ -100,8 +100,7 @@ bool CDecalDataFactory::CreateDPSM(CDecalDescription* desc, CInputStream& in, CS return true; } -void CDecalDataFactory::GetQuadDecalInfo(CInputStream& in, CSimplePool* resPool, FourCC clsId, - CDecalDescription::SQuadDescr& quad) +void CDecalDataFactory::GetQuadDecalInfo(CInputStream& in, CSimplePool* resPool, FourCC clsId, SQuadDescr& quad) { switch (clsId) { diff --git a/Runtime/Particle/CDecalDataFactory.hpp b/Runtime/Particle/CDecalDataFactory.hpp index 70ee6c7a8..612316c4f 100644 --- a/Runtime/Particle/CDecalDataFactory.hpp +++ b/Runtime/Particle/CDecalDataFactory.hpp @@ -16,8 +16,7 @@ class CDecalDataFactory { static bool CreateDPSM(CDecalDescription* desc, CInputStream& in, CSimplePool* resPool); static CDecalDescription* CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool); - static void GetQuadDecalInfo(CInputStream& in, CSimplePool* resPool, FourCC clsId, - CDecalDescription::SQuadDescr& quad); + static void GetQuadDecalInfo(CInputStream& in, CSimplePool* resPool, FourCC clsId, SQuadDescr& quad); public: static CDecalDescription* GetGeneratorDesc(CInputStream& in, CSimplePool* resPool); diff --git a/Runtime/Particle/CDecalDescription.hpp b/Runtime/Particle/CDecalDescription.hpp index 24e9cff3b..5775042f3 100644 --- a/Runtime/Particle/CDecalDescription.hpp +++ b/Runtime/Particle/CDecalDescription.hpp @@ -10,22 +10,22 @@ namespace urde { + +struct SQuadDescr +{ + std::unique_ptr x0_LFT; + std::unique_ptr x4_SZE; + std::unique_ptr x8_ROT; + std::unique_ptr xc_OFF; + std::unique_ptr x10_CLR; + std::unique_ptr x14_TEX; + bool x18_ADD = false; +}; + class CDecalDescription { public: - struct SQuadDescr - { - std::unique_ptr x0_LFT; - std::unique_ptr x4_SZE; - std::unique_ptr x8_ROT; - std::unique_ptr xc_OFF; - std::unique_ptr x10_CLR; - std::unique_ptr x14_TEX; - bool x18_ADD = false; - }; - - SQuadDescr x0_Quad; - SQuadDescr x1c_Quad; + SQuadDescr x0_Quads[2]; SParticleModel x38_DMDL; std::unique_ptr x48_DLFT; std::unique_ptr x4c_DMOP; diff --git a/Runtime/Particle/CDecalManager.cpp b/Runtime/Particle/CDecalManager.cpp index 6a8072955..d1cbe1072 100644 --- a/Runtime/Particle/CDecalManager.cpp +++ b/Runtime/Particle/CDecalManager.cpp @@ -4,6 +4,7 @@ #include "CStateManager.hpp" #include "Graphics/CBooRenderer.hpp" #include "GameGlobalObjects.hpp" +#include "Graphics/Shaders/CDecalShaders.hpp" namespace urde { @@ -15,24 +16,46 @@ CAssetId CDecalManager::m_LastDecalCreatedAssetId = -1; rstl::reserved_vector CDecalManager::m_DecalPool; rstl::reserved_vector CDecalManager::m_ActiveIndexList; +URDE_DECL_SPECIALIZE_SHADER(CDecalShaders) + void CDecalManager::Initialize() { if (m_PoolInitialized) return; m_DecalPool.clear(); - m_DecalPool.resize(64); + for (int i=0 ; i<64 ; ++i) + m_DecalPool.emplace_back(std::experimental::optional{}, 0, i-1, false); m_FreeIndex = 63; m_PoolInitialized = true; m_DeltaTimeSinceLastDecalCreation = 0.f; m_LastDecalCreatedIndex = -1; m_LastDecalCreatedAssetId = -1; + + /* Compile shaders */ + TShader::Initialize(); +} + +void CDecalManager::Reinitialize() +{ + if (!m_PoolInitialized) + Initialize(); + + m_DecalPool.clear(); + for (int i=0 ; i<64 ; ++i) + m_DecalPool.emplace_back(std::experimental::optional{}, 0, i-1, false); + + m_ActiveIndexList.clear(); + + m_FreeIndex = 63; } void CDecalManager::Shutdown() { - + m_ActiveIndexList.clear(); + m_DecalPool.clear(); + TShader::Shutdown(); } void CDecalManager::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) @@ -40,7 +63,7 @@ void CDecalManager::AddToRenderer(const zeus::CFrustum& frustum, const CStateMan for (s32 idx : m_ActiveIndexList) { CDecalManager::SDecal& decal = m_DecalPool[idx]; - if (decal.x75_flags & 0x2 || mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot) + if (decal.x75_24_notIce || mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot) { const zeus::CVector3f& point = decal.x0_decal->xc_transform.origin; zeus::CAABox aabb(point, point); @@ -50,15 +73,61 @@ void CDecalManager::AddToRenderer(const zeus::CFrustum& frustum, const CStateMan } } +rstl::reserved_vector::iterator +CDecalManager::RemoveFromActiveList(rstl::reserved_vector::iterator it, s32 idx) +{ + it = m_ActiveIndexList.erase(it); + m_DecalPool[idx].x74_index = u8(m_FreeIndex); + m_FreeIndex = idx; + if (m_LastDecalCreatedIndex == m_FreeIndex) + m_LastDecalCreatedIndex = -1; + return it; +} + void CDecalManager::Update(float dt, CStateManager& mgr) { - + m_DeltaTimeSinceLastDecalCreation += dt; + for (auto it = m_ActiveIndexList.begin() ; it != m_ActiveIndexList.end() ;) + { + SDecal& decal = m_DecalPool[*it]; + if (decal.x70_areaId != mgr.GetNextAreaId() || + (decal.x0_decal->x5c_29_modelInvalid && + decal.x0_decal->x5c_30_quad2Invalid && + decal.x0_decal->x5c_31_quad1Invalid)) + { + it = RemoveFromActiveList(it, *it); + continue; + } + decal.x0_decal->Update(dt); + ++it; + } } void CDecalManager::AddDecal(const TToken& decal, const zeus::CTransform& xf, - bool b1, CStateManager& mgr) + bool notIce, CStateManager& mgr) { + if (m_LastDecalCreatedIndex != -1 && m_DeltaTimeSinceLastDecalCreation < 0.75f && + m_LastDecalCreatedAssetId == decal.GetObjectTag()->id) + { + SDecal& existingDecal = m_DecalPool[m_LastDecalCreatedIndex]; + if ((existingDecal.x0_decal->xc_transform.origin - xf.origin).magSquared() < 0.01f) + return; + } + if (m_FreeIndex == -1) + RemoveFromActiveList(m_ActiveIndexList.begin(), m_ActiveIndexList[0]); + + s32 thisIndex = m_FreeIndex; + SDecal& freeDecal = m_DecalPool[thisIndex]; + m_FreeIndex = freeDecal.x74_index; + freeDecal.x0_decal.emplace(decal, xf); + + freeDecal.x70_areaId = mgr.GetNextAreaId(); + freeDecal.x75_24_notIce = notIce; + m_DeltaTimeSinceLastDecalCreation = 0.f; + m_LastDecalCreatedIndex = thisIndex; + m_LastDecalCreatedAssetId = decal.GetObjectTag()->id; + m_ActiveIndexList.push_back(thisIndex); } } diff --git a/Runtime/Particle/CDecalManager.hpp b/Runtime/Particle/CDecalManager.hpp index 229eea876..fafa981fd 100644 --- a/Runtime/Particle/CDecalManager.hpp +++ b/Runtime/Particle/CDecalManager.hpp @@ -18,8 +18,10 @@ class CDecalManager { std::experimental::optional x0_decal; TAreaId x70_areaId; - u8 x74_index; - u8 x75_flags : 2; + s8 x74_index; + bool x75_24_notIce : 1; + SDecal(const std::experimental::optional& decal, TAreaId aid, s8 idx, bool notIce) + : x0_decal(decal), x70_areaId(aid), x74_index(idx) { x75_24_notIce = notIce; } }; static bool m_PoolInitialized; @@ -29,13 +31,16 @@ class CDecalManager static CAssetId m_LastDecalCreatedAssetId; static rstl::reserved_vector m_DecalPool; static rstl::reserved_vector m_ActiveIndexList; + static rstl::reserved_vector::iterator + RemoveFromActiveList(rstl::reserved_vector::iterator it, s32 idx); public: static void Initialize(); + static void Reinitialize(); static void Shutdown(); static void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr); static void Update(float dt, CStateManager& mgr); static void AddDecal(const TToken& decal, const zeus::CTransform& xf, - bool b1, CStateManager& mgr); + bool notIce, CStateManager& mgr); }; } diff --git a/Runtime/Particle/CElementGen.cpp b/Runtime/Particle/CElementGen.cpp index cae65f07d..f69b9ee0c 100644 --- a/Runtime/Particle/CElementGen.cpp +++ b/Runtime/Particle/CElementGen.cpp @@ -26,35 +26,9 @@ bool CElementGen::g_ParticleSystemInitialized = false; bool CElementGen::sMoveRedToAlphaBuffer = false; CParticle* CElementGen::g_currentParticle = nullptr; -struct SParticleInstanceTex -{ - zeus::CVector4f pos[4]; - zeus::CColor color; - zeus::CVector2f uvs[4]; -}; -static std::vector g_instTexData; - -struct SParticleInstanceIndTex -{ - zeus::CVector4f pos[4]; - zeus::CColor color; - zeus::CVector4f texrTindUVs[4]; - zeus::CVector4f sceneUVs; -}; -static std::vector g_instIndTexData; - -struct SParticleInstanceNoTex -{ - zeus::CVector4f pos[4]; - zeus::CColor color; -}; -static std::vector g_instNoTexData; - -struct SParticleUniforms -{ - zeus::CMatrix4f mvp; - zeus::CColor moduColor; -}; +std::vector g_instTexData; +std::vector g_instIndTexData; +std::vector g_instNoTexData; void CElementGen::Initialize() { diff --git a/Runtime/Particle/CParticleGlobals.hpp b/Runtime/Particle/CParticleGlobals.hpp index 8e096f57f..3f9f1583c 100644 --- a/Runtime/Particle/CParticleGlobals.hpp +++ b/Runtime/Particle/CParticleGlobals.hpp @@ -2,6 +2,8 @@ #define __URDE_CPARTICLEGLOBALS_HPP__ #include "zeus/CVector3f.hpp" +#include "zeus/CVector4f.hpp" +#include "zeus/CMatrix4f.hpp" #include "zeus/CColor.hpp" #include "RetroTypes.hpp" #include @@ -50,6 +52,36 @@ public: static SParticleSystem* g_currentParticleSystem; }; +struct SParticleInstanceTex +{ + zeus::CVector4f pos[4]; + zeus::CColor color; + zeus::CVector2f uvs[4]; +}; +extern std::vector g_instTexData; + +struct SParticleInstanceIndTex +{ + zeus::CVector4f pos[4]; + zeus::CColor color; + zeus::CVector4f texrTindUVs[4]; + zeus::CVector4f sceneUVs; +}; +extern std::vector g_instIndTexData; + +struct SParticleInstanceNoTex +{ + zeus::CVector4f pos[4]; + zeus::CColor color; +}; +extern std::vector g_instNoTexData; + +struct SParticleUniforms +{ + zeus::CMatrix4f mvp; + zeus::CColor moduColor; +}; + } #endif // __URDE_CPARTICLEGLOBALS_HPP__ diff --git a/Runtime/Weapon/CEnergyProjectile.cpp b/Runtime/Weapon/CEnergyProjectile.cpp index 9ad3ad4f1..ef60e4eb4 100644 --- a/Runtime/Weapon/CEnergyProjectile.cpp +++ b/Runtime/Weapon/CEnergyProjectile.cpp @@ -338,6 +338,7 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3 if (auto particle = x170_projectile.CollisionOccured(type, !done, retargetPlayer, offsetPos, normal, targetPos)) { zeus::CTransform particleXf = zeus::lookAt(zeus::CVector3f::skZero, normal); + particleXf.origin = offsetPos; if (xf0_weaponType != EWeaponType::Power || !xf8_filter.GetExcludeList().HasMaterial(EMaterialTypes::Player) || !x2e4_27_inWater)