From 2d786e43188c049805af3a18280b866892ff7181 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Tue, 29 Sep 2020 05:54:12 -0400 Subject: [PATCH] CDecalShaders: Convert to hsh pipeline --- Runtime/Graphics/CMakeLists.txt | 1 + Runtime/Graphics/Shaders/CDecalShaders.cpp | 92 +++++++--------- Runtime/Graphics/Shaders/CDecalShaders.hpp | 14 +-- Runtime/Particle/CDecal.cpp | 118 ++++++++++----------- Runtime/Particle/CDecal.hpp | 10 +- 5 files changed, 107 insertions(+), 128 deletions(-) diff --git a/Runtime/Graphics/CMakeLists.txt b/Runtime/Graphics/CMakeLists.txt index 6052e3168..dc5528b2b 100644 --- a/Runtime/Graphics/CMakeLists.txt +++ b/Runtime/Graphics/CMakeLists.txt @@ -57,4 +57,5 @@ runtime_add_hsh(Graphics Shaders/CFogVolumePlaneShader.cpp Shaders/CAABoxShader.cpp Shaders/CColoredStripShader.cpp + Shaders/CDecalShaders.cpp ) diff --git a/Runtime/Graphics/Shaders/CDecalShaders.cpp b/Runtime/Graphics/Shaders/CDecalShaders.cpp index ab2dc6045..3db79f1c4 100644 --- a/Runtime/Graphics/Shaders/CDecalShaders.cpp +++ b/Runtime/Graphics/Shaders/CDecalShaders.cpp @@ -4,69 +4,51 @@ #include "Runtime/Particle/CDecal.hpp" -#include +#include "CDecalShaders.cpp.hshhead" namespace urde { +using namespace hsh::pipeline; -void CDecalShaders::Initialize() { - m_texZTestNoZWrite = hecl::conv->convert(Shader_CDecalShaderTexZTest{}); - m_texAdditiveZTest = hecl::conv->convert(Shader_CDecalShaderTexAdditiveZTest{}); - m_texRedToAlphaZTest = hecl::conv->convert(Shader_CDecalShaderTexRedToAlphaZTest{}); - m_noTexZTestNoZWrite = hecl::conv->convert(Shader_CDecalShaderNoTexZTest{}); - m_noTexAdditiveZTest = hecl::conv->convert(Shader_CDecalShaderNoTexAdditiveZTest{}); -} +template +struct CDecalShaderTexPipeline +: pipeline, AdditiveAttachment<>>, + BlendAttachment<>>, + depth_compare, depth_write> { + CDecalShaderTexPipeline(hsh::vertex_buffer vbo, hsh::uniform_buffer uniBuf, + hsh::texture2d tex) { + this->position = uniBuf->mvp * vbo->pos[this->vertex_id]; + this->color_out[0] = vbo->color * uniBuf->moduColor * tex.sample(vbo->uvs[this->vertex_id]); + if constexpr (RedToAlpha) { + this->color_out[0].w = this->color_out[0].x; + } + } +}; +template struct CDecalShaderTexPipeline; +template struct CDecalShaderTexPipeline; +template struct CDecalShaderTexPipeline; -void CDecalShaders::Shutdown() { - m_texZTestNoZWrite.reset(); - m_texAdditiveZTest.reset(); - m_texRedToAlphaZTest.reset(); - m_noTexZTestNoZWrite.reset(); - m_noTexAdditiveZTest.reset(); -} - -void CDecalShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CQuadDecal& decal) { - boo::ObjToken regPipeline; - boo::ObjToken redToAlphaPipeline; +template +struct CDecalShaderNoTexPipeline : pipeline, BlendAttachment<>>, + depth_compare, depth_write> { + CDecalShaderNoTexPipeline(hsh::vertex_buffer vbo, + hsh::uniform_buffer uniBuf) { + this->position = uniBuf->mvp * vbo->pos[this->vertex_id]; + this->color_out[0] = vbo->color * uniBuf->moduColor; + } +}; +template struct CDecalShaderNoTexPipeline; +template struct CDecalShaderNoTexPipeline; +hsh::binding& CDecalShaders::BuildShaderDataBinding(CQuadDecal& decal, hsh::texture2d tex) { + bool additive = decal.m_desc->x18_ADD; if (decal.m_desc->x14_TEX) { - if (decal.m_desc->x18_ADD) - regPipeline = m_texAdditiveZTest; - else - regPipeline = m_texZTestNoZWrite; - redToAlphaPipeline = m_texRedToAlphaZTest; + bool redToAlpha = additive && CDecal::GetMoveRedToAlphaBuffer(); + m_dataBind.hsh_tex_bind( + CDecalShaderTexPipeline(decal.m_instBuf.get(), decal.m_uniformBuf.get(), tex)); } else { - if (decal.m_desc->x18_ADD) - regPipeline = m_noTexAdditiveZTest; - else - regPipeline = m_noTexZTestNoZWrite; - } - - const SQuadDescr* const desc = decal.m_desc; - const CUVElement* const texr = desc->x14_TEX.get(); - size_t texCount = 0; - std::array, 1> textures; - - if (texr != nullptr) { - textures[0] = texr->GetValueTexture(0).GetObj()->GetBooTexture(); - texCount = 1; - } - - if (!decal.m_instBuf) { - return; - } - - std::array, 1> uniforms{decal.m_uniformBuf.get()}; - - if (regPipeline) { - decal.m_normalDataBind = - ctx.newShaderDataBinding(regPipeline, nullptr, decal.m_instBuf.get(), nullptr, uniforms.size(), uniforms.data(), - nullptr, texCount, textures.data(), nullptr, nullptr); - } - if (redToAlphaPipeline) { - decal.m_redToAlphaDataBind = - ctx.newShaderDataBinding(redToAlphaPipeline, nullptr, decal.m_instBuf.get(), nullptr, uniforms.size(), - uniforms.data(), nullptr, texCount, textures.data(), nullptr, nullptr); + m_dataBind.hsh_notex_bind(CDecalShaderNoTexPipeline(decal.m_instBuf.get(), decal.m_uniformBuf.get())); } + return m_dataBind; } } // namespace urde diff --git a/Runtime/Graphics/Shaders/CDecalShaders.hpp b/Runtime/Graphics/Shaders/CDecalShaders.hpp index a25386c0d..cfe5568c3 100644 --- a/Runtime/Graphics/Shaders/CDecalShaders.hpp +++ b/Runtime/Graphics/Shaders/CDecalShaders.hpp @@ -1,23 +1,15 @@ #pragma once -#include +#include "hsh/hsh.h" namespace urde { struct CQuadDecal; class CDecalShaders { -private: - static inline boo::ObjToken m_texZTestNoZWrite; - static inline boo::ObjToken m_texAdditiveZTest; - static inline boo::ObjToken m_texRedToAlphaZTest; - - static inline boo::ObjToken m_noTexZTestNoZWrite; - static inline boo::ObjToken m_noTexAdditiveZTest; + hsh::binding m_dataBind; public: - static void Initialize(); - static void Shutdown(); - static void BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CQuadDecal& decal); + hsh::binding& BuildShaderDataBinding(CQuadDecal& decal, hsh::texture2d tex); }; } // namespace urde diff --git a/Runtime/Particle/CDecal.cpp b/Runtime/Particle/CDecal.cpp index 607b68b7d..9b72eac57 100644 --- a/Runtime/Particle/CDecal.cpp +++ b/Runtime/Particle/CDecal.cpp @@ -1,7 +1,6 @@ #include "Runtime/Particle/CDecal.hpp" #include "Runtime/Graphics/CModel.hpp" -#include "Runtime/Graphics/Shaders/CDecalShaders.hpp" #include "Runtime/Particle/CParticleGlobals.hpp" namespace urde { @@ -18,38 +17,36 @@ CDecal::CDecal(const TToken& desc, const zeus::CTransform& xf CDecalDescription* d = x0_description.GetObj(); if (d->x38_DMDL) { - if (d->x48_DLFT) + if (d->x48_DLFT) { d->x48_DLFT->GetValue(0, x54_modelLifetime); - else + } else { x54_modelLifetime = 0x7FFFFF; + } - if (d->x50_DMRT) + if (d->x50_DMRT) { d->x50_DMRT->GetValue(0, x60_rotation); + } } else { x5c_29_modelInvalid = true; } - - CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) { - for (auto& decal : x3c_decalQuads) { - 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; - } BooTrace); } bool CDecal::InitQuad(CQuadDecal& quad, const SQuadDescr& desc) { quad.m_desc = &desc; if (desc.x14_TEX) { - if (desc.x0_LFT) + quad.m_instBuf = hsh::create_dynamic_vertex_buffer(1); + } else { + quad.m_instBuf = hsh::create_dynamic_vertex_buffer(1); + } + quad.m_uniformBuf = hsh::create_dynamic_uniform_buffer(); + + if (desc.x14_TEX) { + if (desc.x0_LFT) { desc.x0_LFT->GetValue(0, quad.x4_lifetime); - else + } else { quad.x4_lifetime = 0x7FFFFF; + } + if (desc.x8_ROT) { desc.x8_ROT->GetValue(0, quad.x8_rotation); quad.x0_24_invalid = desc.x8_ROT->IsConstant(); @@ -57,13 +54,16 @@ bool CDecal::InitQuad(CQuadDecal& quad, const SQuadDescr& desc) { if (desc.x4_SZE) { quad.x0_24_invalid = desc.x4_SZE->IsConstant(); - float size = 1.f; - desc.x4_SZE->GetValue(0, size); - quad.x0_24_invalid = size <= 1.f; + if (!quad.x0_24_invalid) { + float size = 1.f; + desc.x4_SZE->GetValue(0, size); + quad.x0_24_invalid = size <= 1.f; + } } - if (desc.xc_OFF) + if (desc.xc_OFF) { quad.x0_24_invalid = desc.xc_OFF->IsFastConstant(); + } return false; } @@ -75,18 +75,20 @@ void CDecal::SetGlobalSeed(u16 seed) { sDecalRandom.SetSeed(seed); } void CDecal::SetMoveRedToAlphaBuffer(bool move) { sMoveRedToAlphaBuffer = move; } -void CDecal::RenderQuad(CQuadDecal& decal, const SQuadDescr& desc) const { +void CDecal::RenderQuad(CQuadDecal& decal, const SQuadDescr& desc) { zeus::CColor color = zeus::skWhite; float size = 1.f; zeus::CVector3f offset; - if (CColorElement* clr = desc.x10_CLR.get()) + 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()) + 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; @@ -96,71 +98,69 @@ void CDecal::RenderQuad(CQuadDecal& decal, const SQuadDescr& desc) const { 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; + CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(), + {1.f, 1.f, 1.f, 1.f}, + }; + decal.m_uniformBuf.load(uniformData); 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()) + 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); SParticleInstanceTex& inst = g_instTexData.emplace_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); + inst.pos[0] = hsh::float4(-size, 0.001f, size, 1.f); + inst.pos[1] = hsh::float4(size, 0.001f, size, 1.f); + inst.pos[2] = hsh::float4(-size, 0.001f, -size, 1.f); + inst.pos[3] = hsh::float4(size, 0.001f, -size, 1.f); } 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.pos[0] = hsh::float4(sinSize - cosSize, 0.001f, cosSize + sinSize, 1.f); + inst.pos[1] = hsh::float4(cosSize + sinSize, 0.001f, cosSize - sinSize, 1.f); + inst.pos[2] = hsh::float4(-(cosSize + sinSize), 0.001f, -(cosSize - sinSize), 1.f); + inst.pos[3] = hsh::float4(-sinSize + cosSize, 0.001f, -cosSize - sinSize, 1.f); } 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); + inst.uvs[0] = hsh::float2(uvSet.xMin, uvSet.yMin); + inst.uvs[1] = hsh::float2(uvSet.xMax, uvSet.yMin); + inst.uvs[2] = hsh::float2(uvSet.xMin, uvSet.yMax); + inst.uvs[3] = hsh::float2(uvSet.xMax, uvSet.yMax); - decal.m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex)); - CGraphics::DrawInstances(0, 4, g_instTexData.size()); + decal.m_instBuf.load(hsh::detail::ArrayProxy{g_instTexData.data(), g_instTexData.size()}); + m_shaderBuilder.BuildShaderDataBinding(decal, texObj->GetBooTexture()) + .draw_instanced(0, 4, g_instIndTexData.size()); } else { g_instNoTexData.clear(); g_instNoTexData.reserve(1); SParticleInstanceNoTex& inst = g_instNoTexData.emplace_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); + inst.pos[0] = hsh::float4(-size, 0.001f, size, 1.f); + inst.pos[1] = hsh::float4(size, 0.001f, size, 1.f); + inst.pos[2] = hsh::float4(-size, 0.001f, -size, 1.f); + inst.pos[3] = hsh::float4(size, 0.001f, -size, 1.f); } 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.pos[0] = hsh::float4(sinSize - cosSize, 0.001f, cosSize + sinSize, 1.f); + inst.pos[1] = hsh::float4(cosSize + sinSize, 0.001f, cosSize - sinSize, 1.f); + inst.pos[2] = hsh::float4(-(cosSize + sinSize), 0.001f, -(cosSize - sinSize), 1.f); + inst.pos[3] = hsh::float4(-sinSize + cosSize, 0.001f, -cosSize - sinSize, 1.f); } inst.color = color; - decal.m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex)); - CGraphics::DrawInstances(0, 4, g_instNoTexData.size()); + decal.m_instBuf.load(hsh::detail::ArrayProxy{g_instNoTexData.data(), g_instNoTexData.size()}); + m_shaderBuilder.BuildShaderDataBinding(decal, hsh::texture2d{}).draw_instanced(0, 4, g_instNoTexData.size()); } } diff --git a/Runtime/Particle/CDecal.hpp b/Runtime/Particle/CDecal.hpp index 9ba9597b6..0b7e92b11 100644 --- a/Runtime/Particle/CDecal.hpp +++ b/Runtime/Particle/CDecal.hpp @@ -4,9 +4,10 @@ #include "Runtime/CRandom16.hpp" #include "Runtime/CToken.hpp" -#include "Runtime/RetroTypes.hpp" +#include "Runtime/Graphics/Shaders/CDecalShaders.hpp" #include "Runtime/Particle/CDecalDescription.hpp" #include "Runtime/Particle/CParticleGlobals.hpp" +#include "Runtime/RetroTypes.hpp" #include #include @@ -23,7 +24,6 @@ struct CQuadDecal { hsh::dynamic_owner m_instBuf; hsh::dynamic_owner> m_uniformBuf; - hsh::binding m_dataBind; }; class CDecal { @@ -40,16 +40,20 @@ class CDecal { bool x5c_30_quad2Invalid : 1 = false; bool x5c_29_modelInvalid : 1 = false; zeus::CVector3f x60_rotation; + + CDecalShaders m_shaderBuilder{}; + bool InitQuad(CQuadDecal& quad, const SQuadDescr& desc); public: CDecal(const TToken& desc, const zeus::CTransform& xf); - void RenderQuad(CQuadDecal& decal, const SQuadDescr& desc) const; + void RenderQuad(CQuadDecal& decal, const SQuadDescr& desc); void RenderMdl(); void Render(); void Update(float dt); static void SetGlobalSeed(u16); + static bool GetMoveRedToAlphaBuffer() { return sMoveRedToAlphaBuffer; }; static void SetMoveRedToAlphaBuffer(bool); }; } // namespace urde