2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-07-04 21:55:52 +00:00

CEnvFxShaders: Convert to hsh pipeline

This commit is contained in:
Luke Street 2020-10-02 21:32:22 -04:00
parent 6c56f6452e
commit b632885c81
6 changed files with 101 additions and 74 deletions

View File

@ -531,9 +531,37 @@ using NoColorAttachment = NoColorAttachmentExt<AlphaWrite ? AlphaMode::AlphaWrit
break; \ break; \
} }
#define FOG_SHADER_UNIFORM(fogUniBuf) \
float fogZ; \
float fogF = hsh::saturate(((fogUniBuf)->m_A / ((fogUniBuf)->m_B - this->position.z)) - (fogUniBuf)->m_C); \
switch ((fogUniBuf)->m_mode) { \
case ERglFogMode::PerspLin: \
fogZ = fogF; \
break; \
case ERglFogMode::PerspExp: \
fogZ = 1.0 - hsh::exp2(-8.0 * fogF); \
break; \
case ERglFogMode::PerspExp2: \
fogZ = 1.0 - hsh::exp2(-8.0 * fogF * fogF); \
break; \
case ERglFogMode::PerspRevExp: \
fogZ = hsh::exp2(-8.0 * (1.0 - fogF)); \
break; \
case ERglFogMode::PerspRevExp2: \
fogF = 1.0 - fogF; \
fogZ = hsh::exp2(-8.0 * fogF * fogF); \
break; \
default: \
fogZ = 0.0; \
break; \
}
#define FOG_OUT(out, fog, colorIn) \ #define FOG_OUT(out, fog, colorIn) \
out = hsh::float4(hsh::lerp((colorIn), (fog).m_color, hsh::saturate(fogZ)).xyz(), (colorIn).w); out = hsh::float4(hsh::lerp((colorIn), (fog).m_color, hsh::saturate(fogZ)).xyz(), (colorIn).w);
#define FOG_OUT_UNIFORM(out, fogUniBuf, colorIn) \
out = hsh::float4(hsh::lerp((colorIn), (fogUniBuf)->m_color, hsh::saturate(fogZ)).xyz(), (colorIn).w);
template <ERglCullMode CullMode> template <ERglCullMode CullMode>
struct ERglCullModeAttachmentExt { struct ERglCullModeAttachmentExt {
using type = hsh::pipeline::cull_mode<>; using type = hsh::pipeline::cull_mode<>;

View File

@ -62,4 +62,5 @@ runtime_add_hsh(Graphics
Shaders/CThermalColdFilter.cpp Shaders/CThermalColdFilter.cpp
Shaders/CThermalHotFilter.cpp Shaders/CThermalHotFilter.cpp
Shaders/CElementGenShaders.cpp Shaders/CElementGenShaders.cpp
Shaders/CEnvFxShaders.cpp
) )

View File

@ -2,44 +2,50 @@
#include "Runtime/World/CEnvFxManager.hpp" #include "Runtime/World/CEnvFxManager.hpp"
#include <hecl/Pipeline.hpp> #include "CEnvFxShaders.cpp.hshhead"
namespace urde { namespace urde {
using namespace hsh::pipeline;
void CEnvFxShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CEnvFxManager& fxMgr, template <bool Blend>
CEnvFxManagerGrid& grid) { struct CEnvFxShadersPipeline
const auto uBufInfo = grid.m_uniformBuf.getBufferInfo(); // FIXME replace MultiplyAttachment with ERglBlendFactor One:One equivalent
const auto iBufInfo = grid.m_instBuf.getBufferInfo(); : pipeline<topology<hsh::TriangleStrip>, std::conditional_t<Blend, BlendAttachment<false>, MultiplyAttachment<false>>,
depth_compare<hsh::LEqual>, depth_write<false>> {
CEnvFxShadersPipeline(hsh::vertex_buffer<CEnvFxShaders::Instance> vbo,
hsh::uniform_buffer<CEnvFxShaders::Uniform> envFxUniBuf,
hsh::uniform_buffer<CGraphics::CFogState> fogUniBuf, hsh::texture2d texFlake,
hsh::texture2d texEnv) {
hsh::float4 posIn = hsh::float4(vbo->positions[this->vertex_id], 1.f);
hsh::float4 flakeTexel = texFlake.sample<float>(vbo->uvs[this->vertex_id]);
hsh::float4 envTexel = texEnv.sample<float>(
(envFxUniBuf->envMtx * posIn).xy(),
// FIXME hsh bug: this appears to be completely ignored
hsh::sampler{hsh::Linear, hsh::Linear, hsh::Linear, hsh::ClampToEdge, hsh::ClampToEdge, hsh::ClampToEdge});
hsh::float4 color = vbo->color * envFxUniBuf->moduColor * flakeTexel * envTexel;
this->position = envFxUniBuf->proj * (envFxUniBuf->mv * posIn);
FOG_SHADER_UNIFORM(fogUniBuf)
// FIXME: hsh binds fog uniform to fragment stage
// only because of m_color reference in here. can/should we avoid that?
FOG_OUT_UNIFORM(this->color_out[0], fogUniBuf, color)
}
};
template struct CEnvFxShadersPipeline<true>;
template struct CEnvFxShadersPipeline<false>;
const std::array<boo::ObjToken<boo::IGraphicsBuffer>, 2> uniforms{{ void CEnvFxShaders::BuildShaderDataBinding(CEnvFxManager& fxMgr, CEnvFxManagerGrid& grid) {
uBufInfo.first.get(), hsh::texture2d texFlake = fxMgr.xb74_txtrSnowFlake->GetBooTexture();
fxMgr.m_fogUniformBuf.get(), hsh::texture2d texEnv = fxMgr.x40_txtrEnvGradient->GetBooTexture();
}}; hsh::vertex_buffer<Instance> vboBuf = grid.m_instBuf.get();
const std::array<size_t, 2> ubufOffsets{ hsh::uniform_buffer<Uniform> envFxUniBuf = grid.m_uniformBuf.get();
size_t(uBufInfo.second), hsh::uniform_buffer<CGraphics::CFogState> fogUniBuf = fxMgr.m_fogUniformBuf.get();
0, // FIXME hsh bug: can't bind all constant values
}; bool isUnderwater = false;
constexpr std::array<size_t, 2> ubufSizes{ grid.m_snowBinding.hsh_snow_bind(
sizeof(CEnvFxShaders::Uniform), CEnvFxShadersPipeline<isUnderwater>(vboBuf, envFxUniBuf, fogUniBuf, texFlake, texEnv));
sizeof(CGraphics::g_Fog), isUnderwater = true;
}; grid.m_underwaterBinding.hsh_underwater_bind(
constexpr std::array<boo::PipelineStage, 2> uniformStages{ CEnvFxShadersPipeline<isUnderwater>(vboBuf, envFxUniBuf, fogUniBuf, texFlake, texEnv));
boo::PipelineStage::Vertex,
boo::PipelineStage::Fragment,
};
std::array<boo::ObjToken<boo::ITexture>, 2> textures{
fxMgr.xb74_txtrSnowFlake->GetBooTexture(),
fxMgr.x40_txtrEnvGradient->GetBooTexture(),
};
grid.m_snowBinding = ctx.newShaderDataBinding(
m_snowPipeline, nullptr, iBufInfo.first.get(), nullptr, uniforms.size(), uniforms.data(), uniformStages.data(),
ubufOffsets.data(), ubufSizes.data(), textures.size(), textures.data(), nullptr, nullptr, 0, iBufInfo.second);
textures[0] = fxMgr.xc48_underwaterFlake->GetBooTexture();
grid.m_underwaterBinding =
ctx.newShaderDataBinding(m_underwaterPipeline, nullptr, iBufInfo.first.get(), nullptr, uniforms.size(),
uniforms.data(), uniformStages.data(), ubufOffsets.data(), ubufSizes.data(),
textures.size(), textures.data(), nullptr, nullptr, 0, iBufInfo.second);
} }
} // namespace urde } // namespace urde

View File

@ -2,6 +2,8 @@
#include <array> #include <array>
#include "hsh/hsh.h"
namespace urde { namespace urde {
class CEnvFxManager; class CEnvFxManager;
class CEnvFxManagerGrid; class CEnvFxManagerGrid;
@ -20,8 +22,7 @@ public:
hsh::float4 moduColor; hsh::float4 moduColor;
}; };
static void BuildShaderDataBinding(CEnvFxManager& fxMgr, static void BuildShaderDataBinding(CEnvFxManager& fxMgr, CEnvFxManagerGrid& grid);
CEnvFxManagerGrid& grid);
}; };
} // namespace urde } // namespace urde

View File

@ -16,7 +16,8 @@ struct CThermalColdFilterPipeline : pipeline<topology<hsh::TriangleStrip>,
CThermalColdFilterPipeline(hsh::vertex_buffer<CThermalColdFilter::Vert> vbo, CThermalColdFilterPipeline(hsh::vertex_buffer<CThermalColdFilter::Vert> vbo,
hsh::uniform_buffer<CThermalColdFilter::Uniform> ubo, hsh::render_texture2d sceneTex, hsh::uniform_buffer<CThermalColdFilter::Uniform> ubo, hsh::render_texture2d sceneTex,
hsh::texture2d noiseTex) { hsh::texture2d noiseTex) {
static hsh::float4 kRGBToYPrime = {0.257f, 0.504f, 0.098f, 0.f}; // FIXME hsh bug: cannot be const or static
hsh::float4 kRGBToYPrime{0.257f, 0.504f, 0.098f, 0.f};
this->position = hsh::float4(vbo->m_pos, 0.f, 1.f); this->position = hsh::float4(vbo->m_pos, 0.f, 1.f);
hsh::float4 noiseTexel = noiseTex.read<float>(Lookup8BPP(vbo->m_uvNoise, ubo->m_randOff)); hsh::float4 noiseTexel = noiseTex.read<float>(Lookup8BPP(vbo->m_uvNoise, ubo->m_randOff));

View File

@ -17,40 +17,34 @@
#include "TCastTo.hpp" // Generated file, do not modify include path #include "TCastTo.hpp" // Generated file, do not modify include path
namespace urde { namespace urde {
static rstl::reserved_vector<zeus::CVector2f, 256> g_SnowForces; static rstl::reserved_vector<zeus::CVector2f, 256> g_SnowForces;
CEnvFxManagerGrid::CEnvFxManagerGrid(const zeus::CVector2i& position, const zeus::CVector2i& extent, CEnvFxManagerGrid::CEnvFxManagerGrid(const zeus::CVector2i& position, const zeus::CVector2i& extent,
std::vector<CVectorFixed8_8> initialParticles, int reserve, CEnvFxManager& parent, std::vector<CVectorFixed8_8> initialParticles, int reserve, CEnvFxManager& parent)
boo::IGraphicsDataFactory::Context& ctx)
: x4_position(position) : x4_position(position)
, xc_extent(extent) , xc_extent(extent)
, x1c_particles(std::move(initialParticles)) , x1c_particles(std::move(initialParticles))
, m_instBuf(parent.m_instPool.allocateBlock(CGraphics::g_BooFactory, reserve)) , m_instBuf(hsh::create_dynamic_vertex_buffer<CEnvFxShaders::Instance>(reserve))
, m_uniformBuf(parent.m_uniformPool.allocateBlock(CGraphics::g_BooFactory)) , m_uniformBuf(hsh::create_dynamic_uniform_buffer<CEnvFxShaders::Uniform>())
, m_lineRenderer(ctx, CLineRenderer::EPrimitiveMode::Lines, reserve * 2, parent.x40_txtrEnvGradient->GetBooTexture(), , m_lineRenderer(CLineRenderer::EPrimitiveMode::Lines, reserve * 2, parent.x40_txtrEnvGradient->GetBooTexture(), true,
true, true) { hsh::LEqual) {
x1c_particles.reserve(reserve); x1c_particles.reserve(reserve);
CEnvFxShaders::BuildShaderDataBinding(ctx, parent, *this); CEnvFxShaders::BuildShaderDataBinding(parent, *this);
} }
CEnvFxManager::CEnvFxManager() { CEnvFxManager::CEnvFxManager() {
x40_txtrEnvGradient = g_SimplePool->GetObj("TXTR_EnvGradient"); x40_txtrEnvGradient = g_SimplePool->GetObj("TXTR_EnvGradient");
x40_txtrEnvGradient->GetBooTexture()->setClampMode(boo::TextureClampMode::ClampToEdge);
xb58_envRainSplash = g_SimplePool->GetObj("PART_EnvRainSplash"); xb58_envRainSplash = g_SimplePool->GetObj("PART_EnvRainSplash");
xb74_txtrSnowFlake = g_SimplePool->GetObj("TXTR_SnowFlake"); xb74_txtrSnowFlake = g_SimplePool->GetObj("TXTR_SnowFlake");
xc48_underwaterFlake = g_SimplePool->GetObj("TXTR_UnderwaterFlake"); xc48_underwaterFlake = g_SimplePool->GetObj("TXTR_UnderwaterFlake");
CRandom16 random(0); CRandom16 random(0);
CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) { m_fogUniformBuf = hsh::create_dynamic_uniform_buffer<CGraphics::CFogState>();
m_fogUniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(CGraphics::g_Fog), 1); for (int i = 0; i < 8; ++i)
for (int i = 0; i < 8; ++i) for (int j = 0; j < 8; ++j)
for (int j = 0; j < 8; ++j) x50_grids.emplace_back(zeus::CVector2i{j * 2048, i * 2048}, zeus::CVector2i{2048, 2048},
x50_grids.emplace_back(zeus::CVector2i{j * 2048, i * 2048}, zeus::CVector2i{2048, 2048}, std::vector<CVectorFixed8_8>{}, 171, *this);
std::vector<CVectorFixed8_8>{}, 171, *this, ctx);
return true;
} BooTrace);
for (int i = 0; i < 16; ++i) for (int i = 0; i < 16; ++i)
xb84_snowZDeltas.emplace_back(0.f, 0.f, random.Range(-2.f, -4.f)); xb84_snowZDeltas.emplace_back(0.f, 0.f, random.Range(-2.f, -4.f));
} }
@ -77,10 +71,10 @@ void CEnvFxManager::UpdateRainSounds(const CStateManager& mgr) {
zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr);
float rainVol = CalcRainVolume(x30_fxDensity); float rainVol = CalcRainVolume(x30_fxDensity);
if (!xb6a_rainSoundActive) { if (!xb6a_rainSoundActive) {
xb6c_leftRainSound = CSfxManager::AddEmitter(SFXsfx09F0, zeus::skZero3f, zeus::skZero3f, false, xb6c_leftRainSound =
true, 0xff, kInvalidAreaId); CSfxManager::AddEmitter(SFXsfx09F0, zeus::skZero3f, zeus::skZero3f, false, true, 0xff, kInvalidAreaId);
xb70_rightRainSound = CSfxManager::AddEmitter(SFXsfx09F1, zeus::skZero3f, zeus::skZero3f, false, xb70_rightRainSound =
true, 0xff, kInvalidAreaId); CSfxManager::AddEmitter(SFXsfx09F1, zeus::skZero3f, zeus::skZero3f, false, true, 0xff, kInvalidAreaId);
xb6a_rainSoundActive = true; xb6a_rainSoundActive = true;
} }
CSfxManager::UpdateEmitter(xb6c_leftRainSound, camXf.origin - camXf.basis[0], camXf.basis[0], rainVol); CSfxManager::UpdateEmitter(xb6c_leftRainSound, camXf.origin - camXf.basis[0], camXf.basis[0], rainVol);
@ -209,10 +203,9 @@ void CEnvFxManager::UpdateBlockedGrids(CStateManager& mgr, EEnvFxType type, cons
constexpr auto filter = constexpr auto filter =
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid, EMaterialTypes::Trigger}, CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid, EMaterialTypes::Trigger},
{EMaterialTypes::ProjectilePassthrough, EMaterialTypes::SeeThrough}); {EMaterialTypes::ProjectilePassthrough, EMaterialTypes::SeeThrough});
zeus::CVector3f pos = xf * zeus::CVector3f((grid.x4_position + grid.xc_extent * 0).toVec2f() / 256.f) + zeus::CVector3f pos =
zeus::skUp * 500.f; xf * zeus::CVector3f((grid.x4_position + grid.xc_extent * 0).toVec2f() / 256.f) + zeus::skUp * 500.f;
CRayCastResult result = CRayCastResult result = CGameCollision::RayStaticIntersection(mgr, pos, zeus::skDown, 1000.f, filter);
CGameCollision::RayStaticIntersection(mgr, pos, zeus::skDown, 1000.f, filter);
if (result.IsValid()) { if (result.IsValid()) {
if (!blockListBuilt) { if (!blockListBuilt) {
BuildBlockObjectList(blockList, mgr); BuildBlockObjectList(blockList, mgr);
@ -379,7 +372,7 @@ void CEnvFxManagerGrid::RenderSnowParticles(const zeus::CTransform& camXf) {
const zeus::CVector3f xVec = 0.2f * camXf.basis[0]; const zeus::CVector3f xVec = 0.2f * camXf.basis[0];
const zeus::CVector3f zVec = 0.2f * camXf.basis[2]; const zeus::CVector3f zVec = 0.2f * camXf.basis[2];
const zeus::CMatrix4f mvp = CGraphics::GetPerspectiveProjectionMatrix(false) * CGraphics::g_GXModelView.toMatrix4f(); const zeus::CMatrix4f mvp = CGraphics::GetPerspectiveProjectionMatrix(false) * CGraphics::g_GXModelView.toMatrix4f();
auto* bufOut = m_instBuf.access(); auto* bufOut = m_instBuf.map();
for (const auto& particle : x1c_particles) { for (const auto& particle : x1c_particles) {
bufOut->positions[0] = particle.toVec3f(); bufOut->positions[0] = particle.toVec3f();
bufOut->uvs[0] = zeus::CVector2f(0.f, 0.f); bufOut->uvs[0] = zeus::CVector2f(0.f, 0.f);
@ -392,8 +385,8 @@ void CEnvFxManagerGrid::RenderSnowParticles(const zeus::CTransform& camXf) {
bufOut->color = GetFlakeColor(mvp, *bufOut); bufOut->color = GetFlakeColor(mvp, *bufOut);
++bufOut; ++bufOut;
} }
CGraphics::SetShaderDataBinding(m_snowBinding); m_instBuf.unmap();
CGraphics::DrawInstances(0, 4, x1c_particles.size()); m_snowBinding.draw_instanced(0, 4, x1c_particles.size());
} }
void CEnvFxManagerGrid::RenderRainParticles(const zeus::CTransform& camXf) { void CEnvFxManagerGrid::RenderRainParticles(const zeus::CTransform& camXf) {
@ -416,7 +409,7 @@ void CEnvFxManagerGrid::RenderUnderwaterParticles(const zeus::CTransform& camXf)
const zeus::CVector3f xVec = 0.5f * camXf.basis[0]; const zeus::CVector3f xVec = 0.5f * camXf.basis[0];
const zeus::CVector3f zVec = 0.5f * camXf.basis[2]; const zeus::CVector3f zVec = 0.5f * camXf.basis[2];
const zeus::CMatrix4f mvp = CGraphics::GetPerspectiveProjectionMatrix(false) * CGraphics::g_GXModelView.toMatrix4f(); const zeus::CMatrix4f mvp = CGraphics::GetPerspectiveProjectionMatrix(false) * CGraphics::g_GXModelView.toMatrix4f();
auto* bufOut = m_instBuf.access(); auto* bufOut = m_instBuf.map();
for (const auto& particle : x1c_particles) { for (const auto& particle : x1c_particles) {
bufOut->positions[0] = particle.toVec3f(); bufOut->positions[0] = particle.toVec3f();
bufOut->uvs[0] = zeus::CVector2f(0.f, 0.f); bufOut->uvs[0] = zeus::CVector2f(0.f, 0.f);
@ -429,8 +422,8 @@ void CEnvFxManagerGrid::RenderUnderwaterParticles(const zeus::CTransform& camXf)
bufOut->color = GetFlakeColor(mvp, *bufOut); bufOut->color = GetFlakeColor(mvp, *bufOut);
++bufOut; ++bufOut;
} }
CGraphics::SetShaderDataBinding(m_underwaterBinding); m_instBuf.unmap();
CGraphics::DrawInstances(0, 4, x1c_particles.size()); m_underwaterBinding.draw_instanced(0, 4, x1c_particles.size());
} }
void CEnvFxManagerGrid::Render(const zeus::CTransform& xf, const zeus::CTransform& invXf, const zeus::CTransform& camXf, void CEnvFxManagerGrid::Render(const zeus::CTransform& xf, const zeus::CTransform& invXf, const zeus::CTransform& camXf,
@ -452,7 +445,7 @@ void CEnvFxManagerGrid::Render(const zeus::CTransform& xf, const zeus::CTransfor
default: default:
break; break;
} }
m_uniformBuf.access() = parent.m_uniformData; m_uniformBuf.load(parent.m_uniformData);
switch (fxType) { switch (fxType) {
case EEnvFxType::Snow: case EEnvFxType::Snow:
RenderSnowParticles(camXf); RenderSnowParticles(camXf);
@ -561,20 +554,17 @@ void CEnvFxManager::Render(const CStateManager& mgr) {
default: default:
break; break;
} }
m_fogUniformBuf->load(&CGraphics::g_Fog, sizeof(CGraphics::g_Fog)); m_fogUniformBuf.load(CGraphics::g_Fog);
for (auto& grid : x50_grids) for (auto& grid : x50_grids)
grid.Render(xf, invXf, camXf, x30_fxDensity, fxType, *this); grid.Render(xf, invXf, camXf, x30_fxDensity, fxType, *this);
// Backface cull // Backface cull
m_uniformPool.updateBuffers();
m_instPool.updateBuffers();
} }
} }
} }
void CEnvFxManager::AsyncLoadResources(CStateManager& mgr) { void CEnvFxManager::AsyncLoadResources(CStateManager& mgr) {
xb68_envRainSplashId = mgr.AllocateUniqueId(); xb68_envRainSplashId = mgr.AllocateUniqueId();
CHUDBillboardEffect* effect = auto* effect =
new CHUDBillboardEffect(xb58_envRainSplash, {}, xb68_envRainSplashId, true, "VisorRainSplashes", new CHUDBillboardEffect(xb58_envRainSplash, {}, xb68_envRainSplashId, true, "VisorRainSplashes",
CHUDBillboardEffect::GetNearClipDistance(mgr), CHUDBillboardEffect::GetScaleForPOV(mgr), CHUDBillboardEffect::GetNearClipDistance(mgr), CHUDBillboardEffect::GetScaleForPOV(mgr),
zeus::skWhite, zeus::skOne3f, zeus::skZero3f); zeus::skWhite, zeus::skOne3f, zeus::skZero3f);