mirror of https://github.com/AxioDL/metaforce.git
228 lines
6.7 KiB
C++
228 lines
6.7 KiB
C++
#include "Runtime/Camera/CCameraFilter.hpp"
|
|
|
|
#include "Runtime/Factory/CSimplePool.hpp"
|
|
#include "Runtime/GameGlobalObjects.hpp"
|
|
#include "Runtime/Graphics/CCubeRenderer.hpp"
|
|
#include "Runtime/Graphics/CGraphics.hpp"
|
|
#include "Runtime/Graphics/Shaders/CColoredQuadFilter.hpp"
|
|
#include "Runtime/Graphics/Shaders/CRandomStaticFilter.hpp"
|
|
#include "Runtime/Graphics/Shaders/CScanLinesFilter.hpp"
|
|
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp"
|
|
|
|
#include <algorithm>
|
|
#include <zeus/CColor.hpp>
|
|
|
|
namespace metaforce {
|
|
|
|
template <class S>
|
|
void CCameraFilterPass<S>::Update(float dt) {
|
|
if (x10_remTime <= 0.f)
|
|
return;
|
|
|
|
EFilterType origType = x0_curType;
|
|
|
|
x10_remTime = std::max(0.f, x10_remTime - dt);
|
|
x18_curColor = zeus::CColor::lerp(x1c_nextColor, x14_prevColor, x10_remTime / xc_duration);
|
|
|
|
if (x10_remTime == 0.f) {
|
|
x0_curType = x4_nextType;
|
|
if (x0_curType == EFilterType::Passthru) {
|
|
x24_texObj = TLockedToken<CTexture>();
|
|
x20_nextTxtr = {};
|
|
}
|
|
}
|
|
|
|
if (x0_curType == EFilterType::Passthru)
|
|
m_shader = std::nullopt;
|
|
else if (x0_curType != origType)
|
|
m_shader.emplace(x0_curType, x24_texObj);
|
|
}
|
|
|
|
template <class S>
|
|
void CCameraFilterPass<S>::SetFilter(EFilterType type, EFilterShape shape, float time, const zeus::CColor& color,
|
|
CAssetId txtr) {
|
|
if (time == 0.f) {
|
|
xc_duration = 0.f;
|
|
x10_remTime = 0.f;
|
|
|
|
if (txtr.IsValid())
|
|
x24_texObj = g_SimplePool->GetObj({FOURCC('TXTR'), txtr});
|
|
if (type == EFilterType::Passthru)
|
|
m_shader = std::nullopt;
|
|
else if (x0_curType != type || (x20_nextTxtr != txtr && txtr.IsValid()))
|
|
m_shader.emplace(type, x24_texObj);
|
|
|
|
x4_nextType = type;
|
|
x0_curType = type;
|
|
x8_shape = shape;
|
|
x1c_nextColor = color;
|
|
x18_curColor = color;
|
|
x14_prevColor = color;
|
|
x20_nextTxtr = txtr;
|
|
} else {
|
|
EFilterType origType = x0_curType;
|
|
CAssetId origTxtr = x20_nextTxtr;
|
|
|
|
x1c_nextColor = color;
|
|
x14_prevColor = x18_curColor;
|
|
x8_shape = shape;
|
|
x20_nextTxtr = txtr;
|
|
if (txtr.IsValid())
|
|
x24_texObj = g_SimplePool->GetObj({FOURCC('TXTR'), txtr});
|
|
x10_remTime = time;
|
|
xc_duration = time;
|
|
x0_curType = x4_nextType;
|
|
x4_nextType = type;
|
|
if (type == EFilterType::Passthru) {
|
|
if (x0_curType == EFilterType::Multiply)
|
|
x1c_nextColor = zeus::skWhite;
|
|
else if (x0_curType == EFilterType::Add || x0_curType == EFilterType::Blend)
|
|
x1c_nextColor.a() = 0.f;
|
|
} else {
|
|
if (x0_curType == EFilterType::Passthru) {
|
|
if (type == EFilterType::Multiply) {
|
|
x18_curColor = zeus::skWhite;
|
|
} else if (type == EFilterType::Add || type == EFilterType::Blend) {
|
|
x18_curColor = x1c_nextColor;
|
|
x18_curColor.a() = 0.f;
|
|
x14_prevColor = x18_curColor;
|
|
}
|
|
}
|
|
x0_curType = x4_nextType;
|
|
}
|
|
|
|
if (x0_curType == EFilterType::Passthru)
|
|
m_shader = std::nullopt;
|
|
else if (x0_curType != origType || (x20_nextTxtr != origTxtr && x20_nextTxtr.IsValid()))
|
|
m_shader.emplace(x0_curType, x24_texObj);
|
|
}
|
|
}
|
|
|
|
template <class S>
|
|
void CCameraFilterPass<S>::DisableFilter(float time) {
|
|
SetFilter(EFilterType::Passthru, x8_shape, time, zeus::skWhite, {});
|
|
}
|
|
|
|
template <class S>
|
|
void CCameraFilterPass<S>::Draw() {
|
|
if (!m_shader) {
|
|
return;
|
|
}
|
|
m_shader->DrawFilter(x8_shape, x18_curColor, GetT(x4_nextType == EFilterType::Passthru));
|
|
}
|
|
|
|
float CCameraFilterPassBase::GetT(bool invert) const {
|
|
float tmp;
|
|
if (xc_duration == 0.f)
|
|
tmp = 1.f;
|
|
else
|
|
tmp = 1.f - x10_remTime / xc_duration;
|
|
if (invert)
|
|
return 1.f - tmp;
|
|
return tmp;
|
|
}
|
|
|
|
void CCameraFilterPassPoly::SetFilter(EFilterType type, EFilterShape shape, float time, const zeus::CColor& color,
|
|
CAssetId txtr) {
|
|
if (!m_filter || m_shape != shape) {
|
|
m_shape = shape;
|
|
switch (shape) {
|
|
case EFilterShape::Fullscreen:
|
|
case EFilterShape::FullscreenHalvesLeftRight:
|
|
case EFilterShape::FullscreenHalvesTopBottom:
|
|
case EFilterShape::FullscreenQuarters:
|
|
if (txtr.IsValid())
|
|
m_filter = std::make_unique<CCameraFilterPass<CTexturedQuadFilterAlpha>>();
|
|
else
|
|
m_filter = std::make_unique<CCameraFilterPass<CColoredQuadFilter>>();
|
|
break;
|
|
case EFilterShape::CinemaBars:
|
|
m_filter = std::make_unique<CCameraFilterPass<CWideScreenFilter>>();
|
|
break;
|
|
case EFilterShape::ScanLinesEven:
|
|
m_filter = std::make_unique<CCameraFilterPass<CScanLinesFilterEven>>();
|
|
break;
|
|
case EFilterShape::ScanLinesOdd:
|
|
m_filter = std::make_unique<CCameraFilterPass<CScanLinesFilterOdd>>();
|
|
break;
|
|
case EFilterShape::RandomStatic:
|
|
m_filter = std::make_unique<CCameraFilterPass<CRandomStaticFilter>>();
|
|
break;
|
|
case EFilterShape::CookieCutterDepthRandomStatic:
|
|
m_filter = std::make_unique<CCameraFilterPass<CCookieCutterDepthRandomStaticFilter>>();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if (m_filter)
|
|
m_filter->SetFilter(type, shape, time, color, txtr);
|
|
}
|
|
|
|
void CCameraBlurPass::Draw(bool clearDepth) {
|
|
if (x10_curType == EBlurType::NoBlur)
|
|
return;
|
|
|
|
if (x10_curType == EBlurType::Xray) {
|
|
if (!m_xrayShader)
|
|
m_xrayShader.emplace(x0_paletteTex);
|
|
m_xrayShader->draw(x1c_curValue);
|
|
} else {
|
|
if (!m_shader)
|
|
m_shader.emplace();
|
|
m_shader->draw(x1c_curValue, clearDepth);
|
|
if (clearDepth)
|
|
CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_FAR);
|
|
}
|
|
}
|
|
|
|
void CCameraBlurPass::Update(float dt) {
|
|
if (x28_remainingTime > 0.f) {
|
|
x28_remainingTime = std::max(x28_remainingTime - dt, 0.f);
|
|
x1c_curValue = x18_endValue + (x20_startValue - x18_endValue) * x28_remainingTime / x24_totalTime;
|
|
|
|
if (x28_remainingTime != 0.f)
|
|
return;
|
|
|
|
x10_curType = x14_endType;
|
|
}
|
|
}
|
|
|
|
void CCameraBlurPass::SetBlur(EBlurType type, float amount, float duration) {
|
|
if (duration == 0.f) {
|
|
x24_totalTime = 0.f;
|
|
x28_remainingTime = 0.f;
|
|
x18_endValue = amount;
|
|
x1c_curValue = amount;
|
|
x20_startValue = amount;
|
|
|
|
if (x10_curType == EBlurType::NoBlur) {
|
|
if (type == EBlurType::Xray)
|
|
x0_paletteTex = g_SimplePool->GetObj("TXTR_XRayPalette");
|
|
}
|
|
|
|
x14_endType = type;
|
|
x10_curType = type;
|
|
// x2c_usePersistent = b1;
|
|
} else {
|
|
// x2c_usePersistent = b1;
|
|
x24_totalTime = duration;
|
|
x28_remainingTime = duration;
|
|
x18_endValue = x1c_curValue;
|
|
x20_startValue = amount;
|
|
|
|
if (type != x14_endType) {
|
|
if (x10_curType == EBlurType::NoBlur) {
|
|
if (type == EBlurType::Xray)
|
|
x0_paletteTex = g_SimplePool->GetObj("TXTR_XRayPalette");
|
|
x10_curType = type;
|
|
}
|
|
x14_endType = type;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CCameraBlurPass::DisableBlur(float duration) { SetBlur(EBlurType::NoBlur, 0.f, duration); }
|
|
|
|
} // namespace metaforce
|