diff --git a/Runtime/Graphics/CMakeLists.txt b/Runtime/Graphics/CMakeLists.txt index fe19fc8ff..1d14a4405 100644 --- a/Runtime/Graphics/CMakeLists.txt +++ b/Runtime/Graphics/CMakeLists.txt @@ -65,4 +65,5 @@ runtime_add_hsh(Graphics Shaders/CEnvFxShaders.cpp Shaders/CFogVolumeFilter.cpp Shaders/CMapSurfaceShader.cpp + Shaders/CParticleSwooshShaders.cpp ) diff --git a/Runtime/Graphics/Shaders/CParticleSwooshShaders.cpp b/Runtime/Graphics/Shaders/CParticleSwooshShaders.cpp index 1cc6a360c..01812cc4d 100644 --- a/Runtime/Graphics/Shaders/CParticleSwooshShaders.cpp +++ b/Runtime/Graphics/Shaders/CParticleSwooshShaders.cpp @@ -5,57 +5,65 @@ #include "Runtime/Particle/CParticleSwoosh.hpp" #include "Runtime/Particle/CSwooshDescription.hpp" +#include "CParticleSwooshShaders.cpp.hshhead" + namespace urde { +using namespace hsh::pipeline; + +template +struct CParticleSwooshShadersTexPipeline +: pipeline, + std::conditional_t, BlendAttachment>, + depth_compare, depth_write> { + CParticleSwooshShadersTexPipeline(hsh::vertex_buffer vbo, + hsh::uniform_buffer uniBuf, hsh::texture2d tex) { + this->position = uniBuf->m_xf * hsh::float4(vbo->m_pos, 1.f); + this->color_out[0] = vbo->m_color * tex.sample(vbo->m_uv); + } +}; +template struct CParticleSwooshShadersTexPipeline; +template struct CParticleSwooshShadersTexPipeline; + +template +struct CParticleSwooshShadersNoTexPipeline +: pipeline, + std::conditional_t, BlendAttachment>, + depth_compare, depth_write> { + CParticleSwooshShadersNoTexPipeline(hsh::vertex_buffer vbo, + hsh::uniform_buffer uniBuf) { + this->position = uniBuf->m_xf * hsh::float4(vbo->m_pos, 1.f); + this->color_out[0] = vbo->m_color; + } +}; +template struct CParticleSwooshShadersNoTexPipeline; +template struct CParticleSwooshShadersNoTexPipeline; CParticleSwooshShaders::EShaderClass CParticleSwooshShaders::GetShaderClass(CParticleSwoosh& gen) { - CSwooshDescription* desc = gen.GetDesc(); - - if (desc->x3c_TEXR) - return EShaderClass::Tex; - else - return EShaderClass::NoTex; + return gen.GetDesc()->x3c_TEXR ? EShaderClass::Tex : EShaderClass::NoTex; } void CParticleSwooshShaders::BuildShaderDataBinding(CParticleSwoosh& gen) { - CSwooshDescription* desc = gen.GetDesc(); - std::array, 2>* pipeline = nullptr; - - if (desc->x3c_TEXR) { - if (desc->x44_31_AALP) { - if (desc->x45_24_ZBUF) - pipeline = &m_texAdditiveZWrite; - else - pipeline = &m_texAdditiveNoZWrite; - } else { - if (desc->x45_24_ZBUF) - pipeline = &m_texZWrite; - else - pipeline = &m_texNoZWrite; - } - } else { - if (desc->x44_31_AALP) { - if (desc->x45_24_ZBUF) - pipeline = &m_noTexAdditiveZWrite; - else - pipeline = &m_noTexAdditiveNoZWrite; - } else { - if (desc->x45_24_ZBUF) - pipeline = &m_noTexZWrite; - else - pipeline = &m_noTexNoZWrite; - } + auto* desc = gen.GetDesc(); + switch (GetShaderClass(gen)) { + case EShaderClass::Tex: { + hsh::texture2d tex = desc->x3c_TEXR->GetValueTexture(0)->GetBooTexture(); + gen.m_dataBind[0].hsh_tex_noalphawrite_bind( + CParticleSwooshShadersTexPipelinex44_31_AALP, false, desc->x45_24_ZBUF>(gen.m_vertBuf.get(), + gen.m_uniformBuf.get(), tex)); + gen.m_dataBind[1].hsh_tex_alphawrite_bind( + CParticleSwooshShadersTexPipelinex44_31_AALP, true, desc->x45_24_ZBUF>(gen.m_vertBuf.get(), + gen.m_uniformBuf.get(), tex)); + break; + } + case EShaderClass::NoTex: { + gen.m_dataBind[0].hsh_notex_noalphawrite_bind( + CParticleSwooshShadersNoTexPipelinex44_31_AALP, false, desc->x45_24_ZBUF>(gen.m_vertBuf.get(), + gen.m_uniformBuf.get())); + gen.m_dataBind[1].hsh_notex_alphawrite_bind( + CParticleSwooshShadersNoTexPipelinex44_31_AALP, true, desc->x45_24_ZBUF>(gen.m_vertBuf.get(), + gen.m_uniformBuf.get())); + break; } - - const CUVElement* const texr = desc->x3c_TEXR.get(); - const std::array, 1> textures{ - texr ? texr->GetValueTexture(0).GetObj()->GetBooTexture() : nullptr, - }; - - const std::array, 1> uniforms{gen.m_uniformBuf.get()}; - for (size_t i = 0; i < gen.m_dataBind.size(); ++i) { - gen.m_dataBind[i] = - ctx.newShaderDataBinding((*pipeline)[i], gen.m_vertBuf.get(), nullptr, nullptr, uniforms.size(), - uniforms.data(), nullptr, texr ? 1 : 0, textures.data(), nullptr, nullptr); } } diff --git a/Runtime/Particle/CParticleSwoosh.cpp b/Runtime/Particle/CParticleSwoosh.cpp index 0d69faac4..012386a84 100644 --- a/Runtime/Particle/CParticleSwoosh.cpp +++ b/Runtime/Particle/CParticleSwoosh.cpp @@ -66,17 +66,14 @@ CParticleSwoosh::CParticleSwoosh(const TToken& desc, int len if (x1c_desc->x44_29_WIRE) { const int maxVerts = x1b4_LENG * (x1b0_SPLN + 1) * x1b8_SIDE * 12; - m_lineRenderer.reset( - new CLineRenderer(CLineRenderer::EPrimitiveMode::Lines, maxVerts * 2, nullptr, x1d0_25_AALP)); + const bool additive = x1d0_25_AALP; + m_lineRenderer = std::make_unique(CLineRenderer::EPrimitiveMode::Lines, maxVerts * 2, + hsh::texture2d{}, additive, hsh::LEqual); } else { - const auto maxVerts = size_t(x1b4_LENG * (x1b0_SPLN + 1) * x1b8_SIDE * 4); + const auto maxVerts = x1b4_LENG * (x1b0_SPLN + 1) * x1b8_SIDE * 4; m_cachedVerts.reserve(maxVerts); - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { - m_vertBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(CParticleSwooshShaders::Vert), maxVerts); - m_uniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CMatrix4f), 1); - CParticleSwooshShaders::BuildShaderDataBinding(ctx, *this); - return true; - } BooTrace); + m_vertBuf = hsh::create_dynamic_vertex_buffer(maxVerts); + m_uniformBuf = hsh::create_dynamic_uniform_buffer(); } } } @@ -437,7 +434,7 @@ void CParticleSwoosh::RenderNSidedSpline() { m_cachedVerts.push_back({v1, {x1d4_uvs.xMin, x1d4_uvs.yMax}, color}); m_cachedVerts.push_back({v2, {x1d4_uvs.xMax, x1d4_uvs.yMin}, color}); m_cachedVerts.push_back({v3, {x1d4_uvs.xMax, x1d4_uvs.yMax}, color}); - CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + m_dataBind[g_Renderer->IsThermalVisorHotPass() ? 1 : 0].draw(m_cachedVerts.size() - 4, 4); } else { const auto v0 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t0); const auto v1 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t0); @@ -462,7 +459,7 @@ void CParticleSwoosh::RenderNSidedSpline() { m_cachedVerts.push_back({v1, {x1d4_uvs.xMin, x1d4_uvs.yMax}, color}); m_cachedVerts.push_back({v2, {x1d4_uvs.xMax, x1d4_uvs.yMin}, color}); m_cachedVerts.push_back({v3, {x1d4_uvs.xMax, x1d4_uvs.yMax}, color}); - CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + m_dataBind[g_Renderer->IsThermalVisorHotPass() ? 1 : 0].draw(m_cachedVerts.size() - 4, 4); } } } @@ -593,19 +590,19 @@ void CParticleSwoosh::Render3SidedSolidSpline() { m_cachedVerts.push_back({v10, {uv0, x1d4_uvs.yMax}, c0}); m_cachedVerts.push_back({v01, {uv1, x1d4_uvs.yMin}, c1}); m_cachedVerts.push_back({v11, {uv1, x1d4_uvs.yMax}, c1}); - CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + m_dataBind[g_Renderer->IsThermalVisorHotPass() ? 1 : 0].draw(m_cachedVerts.size() - 4, 4); m_cachedVerts.push_back({v10, {uv0, x1d4_uvs.yMin}, c0}); m_cachedVerts.push_back({v20, {uv0, x1d4_uvs.yMax}, c0}); m_cachedVerts.push_back({v11, {uv1, x1d4_uvs.yMin}, c1}); m_cachedVerts.push_back({v21, {uv1, x1d4_uvs.yMax}, c1}); - CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + m_dataBind[g_Renderer->IsThermalVisorHotPass() ? 1 : 0].draw(m_cachedVerts.size() - 4, 4); m_cachedVerts.push_back({v20, {uv0, x1d4_uvs.yMin}, c0}); m_cachedVerts.push_back({v00, {uv0, x1d4_uvs.yMax}, c0}); m_cachedVerts.push_back({v21, {uv1, x1d4_uvs.yMin}, c1}); m_cachedVerts.push_back({v01, {uv1, x1d4_uvs.yMax}, c1}); - CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + m_dataBind[g_Renderer->IsThermalVisorHotPass() ? 1 : 0].draw(m_cachedVerts.size() - 4, 4); } } } @@ -685,19 +682,19 @@ void CParticleSwoosh::Render3SidedSolidNoSplineNoGaps() { m_cachedVerts.push_back({p1[i & 1], {uv0, x1d4_uvs.yMax}, c0}); m_cachedVerts.push_back({p0[!(i & 1)], {uv1, x1d4_uvs.yMin}, c1}); m_cachedVerts.push_back({p1[!(i & 1)], {uv1, x1d4_uvs.yMax}, c1}); - CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + m_dataBind[g_Renderer->IsThermalVisorHotPass() ? 1 : 0].draw(m_cachedVerts.size() - 4, 4); m_cachedVerts.push_back({p1[i & 1], {uv0, x1d4_uvs.yMin}, c0}); m_cachedVerts.push_back({p2[i & 1], {uv0, x1d4_uvs.yMax}, c0}); m_cachedVerts.push_back({p1[!(i & 1)], {uv1, x1d4_uvs.yMin}, c1}); m_cachedVerts.push_back({p2[!(i & 1)], {uv1, x1d4_uvs.yMax}, c1}); - CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + m_dataBind[g_Renderer->IsThermalVisorHotPass() ? 1 : 0].draw(m_cachedVerts.size() - 4, 4); m_cachedVerts.push_back({p2[i & 1], {uv0, x1d4_uvs.yMin}, c0}); m_cachedVerts.push_back({p0[i & 1], {uv0, x1d4_uvs.yMax}, c0}); m_cachedVerts.push_back({p2[!(i & 1)], {uv1, x1d4_uvs.yMin}, c1}); m_cachedVerts.push_back({p0[!(i & 1)], {uv1, x1d4_uvs.yMax}, c1}); - CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + m_dataBind[g_Renderer->IsThermalVisorHotPass() ? 1 : 0].draw(m_cachedVerts.size() - 4, 4); } } @@ -719,7 +716,7 @@ void CParticleSwoosh::Render2SidedNoSplineGaps() { if (!swoosh.x0_active) { if (streaming) { streaming = false; - CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart); + m_dataBind[g_Renderer->IsThermalVisorHotPass() ? 1 : 0].draw(drawStart, m_cachedVerts.size() - drawStart); } continue; } @@ -765,7 +762,7 @@ void CParticleSwoosh::Render2SidedNoSplineGaps() { } if (streaming) - CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart); + m_dataBind[g_Renderer->IsThermalVisorHotPass() ? 1 : 0].draw(drawStart, m_cachedVerts.size() - drawStart); } void CParticleSwoosh::Render2SidedNoSplineNoGaps() { @@ -818,7 +815,8 @@ void CParticleSwoosh::Render2SidedNoSplineNoGaps() { m_cachedVerts.push_back({v0, {uvOffset, x1d4_uvs.yMin}, color}); m_cachedVerts.push_back({v1, {uvOffset, x1d4_uvs.yMax}, color}); if (uvOffset >= 1.f && particleCount) { - CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart); + m_dataBind[g_Renderer->IsThermalVisorHotPass() ? 1 : 0].draw(drawStart, + m_cachedVerts.size() - drawStart); drawStart = m_cachedVerts.size(); uvOffset -= 1.f; m_cachedVerts.push_back({v0, {uvOffset, x1d4_uvs.yMin}, color}); @@ -872,7 +870,7 @@ void CParticleSwoosh::Render2SidedNoSplineNoGaps() { m_cachedVerts.push_back({v0, {uvOffset, x1d4_uvs.yMin}, color}); m_cachedVerts.push_back({v1, {uvOffset, x1d4_uvs.yMax}, color}); if (uvOffset >= 1.f && particleCount) { - CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart); + m_dataBind[g_Renderer->IsThermalVisorHotPass() ? 1 : 0].draw(drawStart, m_cachedVerts.size() - drawStart); drawStart = m_cachedVerts.size(); uvOffset -= 1.f; m_cachedVerts.push_back({v0, {uvOffset, x1d4_uvs.yMin}, color}); @@ -925,7 +923,7 @@ void CParticleSwoosh::Render2SidedNoSplineNoGaps() { } } - CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart); + m_dataBind[g_Renderer->IsThermalVisorHotPass() ? 1 : 0].draw(drawStart, m_cachedVerts.size() - drawStart); } void CParticleSwoosh::Render(const CActorLights*) { @@ -933,13 +931,10 @@ void CParticleSwoosh::Render(const CActorLights*) { return; } - SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CParticleSwoosh::Render {}"), - *x1c_desc.GetObjectTag()).c_str(), zeus::skYellow); + SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CParticleSwoosh::Render {}"), *x1c_desc.GetObjectTag()).c_str(), + zeus::skYellow); m_cachedVerts.clear(); - if (m_dataBind[0]) { - CGraphics::SetShaderDataBinding(m_dataBind[g_Renderer->IsThermalVisorHotPass()]); - } CParticleGlobals::instance()->SetParticleLifetime(x1b4_LENG); CGlobalRandom gr(x1c0_rand); @@ -1007,9 +1002,9 @@ void CParticleSwoosh::Render(const CActorLights*) { } zeus::CMatrix4f mvp = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(); - m_uniformBuf->load(&mvp, sizeof(zeus::CMatrix4f)); - if (m_cachedVerts.size()) { - m_vertBuf->load(m_cachedVerts.data(), m_cachedVerts.size() * sizeof(CParticleSwooshShaders::Vert)); + m_uniformBuf.load({mvp}); + if (!m_cachedVerts.empty()) { + m_vertBuf.load(m_cachedVerts); } } @@ -1074,9 +1069,7 @@ u32 CParticleSwoosh::GetParticleCount() const { return x1ac_particleCount; } bool CParticleSwoosh::SystemHasLight() const { return false; } -CLight CParticleSwoosh::GetLight() const { - return CLight::BuildLocalAmbient(zeus::skZero3f, zeus::skWhite); -} +CLight CParticleSwoosh::GetLight() const { return CLight::BuildLocalAmbient(zeus::skZero3f, zeus::skWhite); } bool CParticleSwoosh::GetParticleEmission() const { return x1d0_24_emitting; } diff --git a/Runtime/Particle/CParticleSwoosh.hpp b/Runtime/Particle/CParticleSwoosh.hpp index e5dae9d7a..7fbaef985 100644 --- a/Runtime/Particle/CParticleSwoosh.hpp +++ b/Runtime/Particle/CParticleSwoosh.hpp @@ -104,7 +104,7 @@ class CParticleSwoosh : public CParticleGen { zeus::CColor x20c_moduColor = zeus::skWhite; std::array m_dataBind; - hsh::owner> m_vertBuf; + hsh::dynamic_owner> m_vertBuf; hsh::dynamic_owner> m_uniformBuf; std::unique_ptr m_lineRenderer; std::vector m_cachedVerts;