2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-07-04 22:35:53 +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; \
}
#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) \
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>
struct ERglCullModeAttachmentExt {
using type = hsh::pipeline::cull_mode<>;

View File

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

View File

@ -2,44 +2,50 @@
#include "Runtime/World/CEnvFxManager.hpp"
#include <hecl/Pipeline.hpp>
#include "CEnvFxShaders.cpp.hshhead"
namespace urde {
using namespace hsh::pipeline;
void CEnvFxShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CEnvFxManager& fxMgr,
CEnvFxManagerGrid& grid) {
const auto uBufInfo = grid.m_uniformBuf.getBufferInfo();
const auto iBufInfo = grid.m_instBuf.getBufferInfo();
template <bool Blend>
struct CEnvFxShadersPipeline
// FIXME replace MultiplyAttachment with ERglBlendFactor One:One equivalent
: 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{{
uBufInfo.first.get(),
fxMgr.m_fogUniformBuf.get(),
}};
const std::array<size_t, 2> ubufOffsets{
size_t(uBufInfo.second),
0,
};
constexpr std::array<size_t, 2> ubufSizes{
sizeof(CEnvFxShaders::Uniform),
sizeof(CGraphics::g_Fog),
};
constexpr std::array<boo::PipelineStage, 2> uniformStages{
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);
void CEnvFxShaders::BuildShaderDataBinding(CEnvFxManager& fxMgr, CEnvFxManagerGrid& grid) {
hsh::texture2d texFlake = fxMgr.xb74_txtrSnowFlake->GetBooTexture();
hsh::texture2d texEnv = fxMgr.x40_txtrEnvGradient->GetBooTexture();
hsh::vertex_buffer<Instance> vboBuf = grid.m_instBuf.get();
hsh::uniform_buffer<Uniform> envFxUniBuf = grid.m_uniformBuf.get();
hsh::uniform_buffer<CGraphics::CFogState> fogUniBuf = fxMgr.m_fogUniformBuf.get();
// FIXME hsh bug: can't bind all constant values
bool isUnderwater = false;
grid.m_snowBinding.hsh_snow_bind(
CEnvFxShadersPipeline<isUnderwater>(vboBuf, envFxUniBuf, fogUniBuf, texFlake, texEnv));
isUnderwater = true;
grid.m_underwaterBinding.hsh_underwater_bind(
CEnvFxShadersPipeline<isUnderwater>(vboBuf, envFxUniBuf, fogUniBuf, texFlake, texEnv));
}
} // namespace urde

View File

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

View File

@ -16,7 +16,8 @@ struct CThermalColdFilterPipeline : pipeline<topology<hsh::TriangleStrip>,
CThermalColdFilterPipeline(hsh::vertex_buffer<CThermalColdFilter::Vert> vbo,
hsh::uniform_buffer<CThermalColdFilter::Uniform> ubo, hsh::render_texture2d sceneTex,
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);
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
namespace urde {
static rstl::reserved_vector<zeus::CVector2f, 256> g_SnowForces;
CEnvFxManagerGrid::CEnvFxManagerGrid(const zeus::CVector2i& position, const zeus::CVector2i& extent,
std::vector<CVectorFixed8_8> initialParticles, int reserve, CEnvFxManager& parent,
boo::IGraphicsDataFactory::Context& ctx)
std::vector<CVectorFixed8_8> initialParticles, int reserve, CEnvFxManager& parent)
: x4_position(position)
, xc_extent(extent)
, x1c_particles(std::move(initialParticles))
, m_instBuf(parent.m_instPool.allocateBlock(CGraphics::g_BooFactory, reserve))
, m_uniformBuf(parent.m_uniformPool.allocateBlock(CGraphics::g_BooFactory))
, m_lineRenderer(ctx, CLineRenderer::EPrimitiveMode::Lines, reserve * 2, parent.x40_txtrEnvGradient->GetBooTexture(),
true, true) {
, m_instBuf(hsh::create_dynamic_vertex_buffer<CEnvFxShaders::Instance>(reserve))
, m_uniformBuf(hsh::create_dynamic_uniform_buffer<CEnvFxShaders::Uniform>())
, m_lineRenderer(CLineRenderer::EPrimitiveMode::Lines, reserve * 2, parent.x40_txtrEnvGradient->GetBooTexture(), true,
hsh::LEqual) {
x1c_particles.reserve(reserve);
CEnvFxShaders::BuildShaderDataBinding(ctx, parent, *this);
CEnvFxShaders::BuildShaderDataBinding(parent, *this);
}
CEnvFxManager::CEnvFxManager() {
x40_txtrEnvGradient = g_SimplePool->GetObj("TXTR_EnvGradient");
x40_txtrEnvGradient->GetBooTexture()->setClampMode(boo::TextureClampMode::ClampToEdge);
xb58_envRainSplash = g_SimplePool->GetObj("PART_EnvRainSplash");
xb74_txtrSnowFlake = g_SimplePool->GetObj("TXTR_SnowFlake");
xc48_underwaterFlake = g_SimplePool->GetObj("TXTR_UnderwaterFlake");
CRandom16 random(0);
CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) {
m_fogUniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(CGraphics::g_Fog), 1);
for (int i = 0; i < 8; ++i)
for (int j = 0; j < 8; ++j)
x50_grids.emplace_back(zeus::CVector2i{j * 2048, i * 2048}, zeus::CVector2i{2048, 2048},
std::vector<CVectorFixed8_8>{}, 171, *this, ctx);
return true;
} BooTrace);
m_fogUniformBuf = hsh::create_dynamic_uniform_buffer<CGraphics::CFogState>();
for (int i = 0; i < 8; ++i)
for (int j = 0; j < 8; ++j)
x50_grids.emplace_back(zeus::CVector2i{j * 2048, i * 2048}, zeus::CVector2i{2048, 2048},
std::vector<CVectorFixed8_8>{}, 171, *this);
for (int i = 0; i < 16; ++i)
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);
float rainVol = CalcRainVolume(x30_fxDensity);
if (!xb6a_rainSoundActive) {
xb6c_leftRainSound = CSfxManager::AddEmitter(SFXsfx09F0, zeus::skZero3f, zeus::skZero3f, false,
true, 0xff, kInvalidAreaId);
xb70_rightRainSound = CSfxManager::AddEmitter(SFXsfx09F1, zeus::skZero3f, zeus::skZero3f, false,
true, 0xff, kInvalidAreaId);
xb6c_leftRainSound =
CSfxManager::AddEmitter(SFXsfx09F0, zeus::skZero3f, zeus::skZero3f, false, true, 0xff, kInvalidAreaId);
xb70_rightRainSound =
CSfxManager::AddEmitter(SFXsfx09F1, zeus::skZero3f, zeus::skZero3f, false, true, 0xff, kInvalidAreaId);
xb6a_rainSoundActive = true;
}
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 =
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid, EMaterialTypes::Trigger},
{EMaterialTypes::ProjectilePassthrough, EMaterialTypes::SeeThrough});
zeus::CVector3f pos = xf * zeus::CVector3f((grid.x4_position + grid.xc_extent * 0).toVec2f() / 256.f) +
zeus::skUp * 500.f;
CRayCastResult result =
CGameCollision::RayStaticIntersection(mgr, pos, zeus::skDown, 1000.f, filter);
zeus::CVector3f pos =
xf * zeus::CVector3f((grid.x4_position + grid.xc_extent * 0).toVec2f() / 256.f) + zeus::skUp * 500.f;
CRayCastResult result = CGameCollision::RayStaticIntersection(mgr, pos, zeus::skDown, 1000.f, filter);
if (result.IsValid()) {
if (!blockListBuilt) {
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 zVec = 0.2f * camXf.basis[2];
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) {
bufOut->positions[0] = particle.toVec3f();
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;
}
CGraphics::SetShaderDataBinding(m_snowBinding);
CGraphics::DrawInstances(0, 4, x1c_particles.size());
m_instBuf.unmap();
m_snowBinding.draw_instanced(0, 4, x1c_particles.size());
}
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 zVec = 0.5f * camXf.basis[2];
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) {
bufOut->positions[0] = particle.toVec3f();
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;
}
CGraphics::SetShaderDataBinding(m_underwaterBinding);
CGraphics::DrawInstances(0, 4, x1c_particles.size());
m_instBuf.unmap();
m_underwaterBinding.draw_instanced(0, 4, x1c_particles.size());
}
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:
break;
}
m_uniformBuf.access() = parent.m_uniformData;
m_uniformBuf.load(parent.m_uniformData);
switch (fxType) {
case EEnvFxType::Snow:
RenderSnowParticles(camXf);
@ -561,20 +554,17 @@ void CEnvFxManager::Render(const CStateManager& mgr) {
default:
break;
}
m_fogUniformBuf->load(&CGraphics::g_Fog, sizeof(CGraphics::g_Fog));
m_fogUniformBuf.load(CGraphics::g_Fog);
for (auto& grid : x50_grids)
grid.Render(xf, invXf, camXf, x30_fxDensity, fxType, *this);
// Backface cull
m_uniformPool.updateBuffers();
m_instPool.updateBuffers();
}
}
}
void CEnvFxManager::AsyncLoadResources(CStateManager& mgr) {
xb68_envRainSplashId = mgr.AllocateUniqueId();
CHUDBillboardEffect* effect =
auto* effect =
new CHUDBillboardEffect(xb58_envRainSplash, {}, xb68_envRainSplashId, true, "VisorRainSplashes",
CHUDBillboardEffect::GetNearClipDistance(mgr), CHUDBillboardEffect::GetScaleForPOV(mgr),
zeus::skWhite, zeus::skOne3f, zeus::skZero3f);