mirror of https://github.com/AxioDL/metaforce.git
Begin transitioning CElementGen RenderParticles & many fixes
This commit is contained in:
parent
a42769627c
commit
fcfa9f0d64
|
@ -365,14 +365,14 @@ u32 CCubeMaterial::HandleAnimatedUV(const u32* uvAnim, GX::TexMtx texMtx, GX::PT
|
||||||
const float* params = reinterpret_cast<const float*>(uvAnim + 1);
|
const float* params = reinterpret_cast<const float*>(uvAnim + 1);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 0: {
|
case 0: {
|
||||||
auto xf = CGraphics::g_GXModelViewInvXpose;
|
auto xf = CGraphics::g_ViewMatrix.inverse().multiplyIgnoreTranslation(CGraphics::g_GXModelMatrix);
|
||||||
|
xf.origin.zeroOut();
|
||||||
GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4);
|
GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4);
|
||||||
GXLoadTexMtxImm(&MvPostXf, pttTexMtx, GX::MTX3x4);
|
GXLoadTexMtxImm(&MvPostXf, pttTexMtx, GX::MTX3x4);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
auto xf = CGraphics::g_GXModelViewInvXpose;
|
auto xf = CGraphics::g_ViewMatrix.inverse() * CGraphics::g_GXModelMatrix;
|
||||||
xf.origin = CGraphics::g_ViewMatrix.inverse() * CGraphics::g_GXModelMatrix.origin;
|
|
||||||
GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4);
|
GXLoadTexMtxImm(&xf, texMtx, GX::MTX3x4);
|
||||||
GXLoadTexMtxImm(&MvPostXf, pttTexMtx, GX::MTX3x4);
|
GXLoadTexMtxImm(&MvPostXf, pttTexMtx, GX::MTX3x4);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -902,7 +902,7 @@ void CCubeRenderer::SetupCGraphicsState() {
|
||||||
void CCubeRenderer::SetupRendererStates(bool depthWrite) {
|
void CCubeRenderer::SetupRendererStates(bool depthWrite) {
|
||||||
CGraphics::DisableAllLights();
|
CGraphics::DisableAllLights();
|
||||||
CGraphics::SetModelMatrix({});
|
CGraphics::SetModelMatrix({});
|
||||||
CGraphics::SetAmbientColor(zeus::skBlack);
|
CGraphics::SetAmbientColor(zeus::skClear);
|
||||||
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, depthWrite);
|
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, depthWrite);
|
||||||
CCubeMaterial::ResetCachedMaterials();
|
CCubeMaterial::ResetCachedMaterials();
|
||||||
GXSetTevColor(GX::TEVREG1, x2fc_tevReg1Color);
|
GXSetTevColor(GX::TEVREG1, x2fc_tevReg1Color);
|
||||||
|
|
|
@ -25,6 +25,14 @@ const CTevPass skPassThru{
|
||||||
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC},
|
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC},
|
||||||
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA},
|
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA},
|
||||||
};
|
};
|
||||||
|
const CTevPass sTevPass804bfcc0{
|
||||||
|
{GX::TevColorArg::CC_C0, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ZERO},
|
||||||
|
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA},
|
||||||
|
};
|
||||||
|
const CTevPass sTevPass804bfe68{
|
||||||
|
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_CPREV, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ZERO},
|
||||||
|
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_APREV, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO},
|
||||||
|
};
|
||||||
const CTevPass sTevPass805a5698{
|
const CTevPass sTevPass805a5698{
|
||||||
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_C0, GX::TevColorArg::CC_ZERO},
|
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_C0, GX::TevColorArg::CC_ZERO},
|
||||||
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_A0, GX::TevAlphaArg::CA_ZERO},
|
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_A0, GX::TevAlphaArg::CA_ZERO},
|
||||||
|
@ -49,10 +57,6 @@ const CTevPass sTevPass805a5fa0{
|
||||||
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_TEXC},
|
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_TEXC},
|
||||||
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA},
|
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA},
|
||||||
};
|
};
|
||||||
const CTevPass sTevPass804bfcc0{
|
|
||||||
{GX::TevColorArg::CC_C0, GX::TevColorArg::CC_TEXC, GX::TevColorArg::CC_RASC, GX::TevColorArg::CC_ZERO},
|
|
||||||
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_RASA},
|
|
||||||
};
|
|
||||||
const CTevPass sTevPass805a5fec{
|
const CTevPass sTevPass805a5fec{
|
||||||
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC},
|
{GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_ZERO, GX::TevColorArg::CC_RASC},
|
||||||
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO},
|
{GX::TevAlphaArg::CA_ZERO, GX::TevAlphaArg::CA_TEXA, GX::TevAlphaArg::CA_RASA, GX::TevAlphaArg::CA_ZERO},
|
||||||
|
|
|
@ -102,13 +102,14 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const CTevPass skPassThru;
|
extern const CTevPass skPassThru;
|
||||||
|
extern const CTevPass sTevPass804bfcc0;
|
||||||
|
extern const CTevPass sTevPass804bfe68;
|
||||||
extern const CTevPass sTevPass805a5698;
|
extern const CTevPass sTevPass805a5698;
|
||||||
extern const CTevPass sTevPass805a5e70;
|
extern const CTevPass sTevPass805a5e70;
|
||||||
extern const CTevPass sTevPass805a5ebc;
|
extern const CTevPass sTevPass805a5ebc;
|
||||||
extern const CTevPass sTevPass805a5f08;
|
extern const CTevPass sTevPass805a5f08;
|
||||||
extern const CTevPass sTevPass805a5f54;
|
extern const CTevPass sTevPass805a5f54;
|
||||||
extern const CTevPass sTevPass805a5fa0;
|
extern const CTevPass sTevPass805a5fa0;
|
||||||
extern const CTevPass sTevPass804bfcc0;
|
|
||||||
extern const CTevPass sTevPass805a5fec;
|
extern const CTevPass sTevPass805a5fec;
|
||||||
extern const CTevPass sTevPass805a6038;
|
extern const CTevPass sTevPass805a6038;
|
||||||
extern const CTevPass sTevPass805a6084;
|
extern const CTevPass sTevPass805a6084;
|
||||||
|
|
|
@ -145,7 +145,7 @@ void CBloodFlower::LaunchPollenProjectile(const zeus::CTransform& xf, CStateMana
|
||||||
|
|
||||||
void CBloodFlower::Render(CStateManager& mgr) {
|
void CBloodFlower::Render(CStateManager& mgr) {
|
||||||
CPatterned::Render(mgr);
|
CPatterned::Render(mgr);
|
||||||
x574_podEffect->Render(GetActorLights());
|
x574_podEffect->Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
EWeaponCollisionResponseTypes CBloodFlower::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&,
|
EWeaponCollisionResponseTypes CBloodFlower::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&,
|
||||||
|
|
|
@ -125,8 +125,10 @@ void CBurrower::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr)
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBurrower::Render(CStateManager& mgr) {
|
void CBurrower::Render(CStateManager& mgr) {
|
||||||
if (GetActorLights() != nullptr && x674_jumpParticle) {
|
auto* lights = GetActorLights();
|
||||||
x674_jumpParticle->Render(GetActorLights());
|
if (lights != nullptr && x674_jumpParticle) {
|
||||||
|
lights->ActivateLights();
|
||||||
|
x674_jumpParticle->Render();
|
||||||
}
|
}
|
||||||
CPatterned::Render(mgr);
|
CPatterned::Render(mgr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,7 +154,7 @@ void CPuddleSpore::Render(CStateManager& mgr) {
|
||||||
CPatterned::Render(mgr);
|
CPatterned::Render(mgr);
|
||||||
if (x56c_ > 0.01f) {
|
if (x56c_ > 0.01f) {
|
||||||
for (const auto& elemGen : x5dc_elemGens)
|
for (const auto& elemGen : x5dc_elemGens)
|
||||||
elemGen->Render(GetActorLights());
|
elemGen->Render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -837,15 +837,7 @@ u32 CElementGen::GetSystemCount() const {
|
||||||
return ret + (x25c_activeParticleCount != 0);
|
return ret + (x25c_activeParticleCount != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CElementGen::Render(const CActorLights* actorLights) {
|
void CElementGen::Render() {
|
||||||
// Check to make sure our buffers are ready to render
|
|
||||||
// if (!x26c_31_LINE) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// if (x28_loadedGenDesc->x45_24_x31_26_PMUS) { // && (!m_instBufPmus || !m_uniformBufPmus)
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CElementGen::Render {}"), *x1c_genDesc.GetObjectTag()).c_str(),
|
SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CElementGen::Render {}"), *x1c_genDesc.GetObjectTag()).c_str(),
|
||||||
zeus::skYellow);
|
zeus::skYellow);
|
||||||
|
|
||||||
|
@ -855,35 +847,27 @@ void CElementGen::Render(const CActorLights* actorLights) {
|
||||||
CGraphics::DisableAllLights();
|
CGraphics::DisableAllLights();
|
||||||
|
|
||||||
for (std::unique_ptr<CParticleGen>& child : x290_activePartChildren)
|
for (std::unique_ptr<CParticleGen>& child : x290_activePartChildren)
|
||||||
child->Render(actorLights);
|
child->Render();
|
||||||
|
|
||||||
CParticleGlobals::SParticleSystem* prevSystem = CParticleGlobals::instance()->m_currentParticleSystem;
|
CParticleGlobals::SParticleSystem* prevSystem = CParticleGlobals::instance()->m_currentParticleSystem;
|
||||||
CParticleGlobals::SParticleSystem thisSystem{FOURCC('PART'), this};
|
CParticleGlobals::SParticleSystem thisSystem{FOURCC('PART'), this};
|
||||||
CParticleGlobals::instance()->m_currentParticleSystem = &thisSystem;
|
CParticleGlobals::instance()->m_currentParticleSystem = &thisSystem;
|
||||||
|
|
||||||
if (x30_particles.size()) {
|
if (!x30_particles.empty()) {
|
||||||
SParticleModel& pmdl = desc->x5c_x48_PMDL;
|
if (desc->x5c_x48_PMDL || desc->x45_24_x31_26_PMUS) {
|
||||||
if (pmdl || desc->x45_24_x31_26_PMUS)
|
RenderModels();
|
||||||
RenderModels(actorLights);
|
}
|
||||||
|
if (x26c_31_LINE) {
|
||||||
if (x26c_31_LINE)
|
|
||||||
RenderLines();
|
RenderLines();
|
||||||
else
|
} else {
|
||||||
RenderParticles();
|
RenderParticles();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CParticleGlobals::instance()->m_currentParticleSystem = prevSystem;
|
CParticleGlobals::instance()->m_currentParticleSystem = prevSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CElementGen::RenderModels(const CActorLights* actorLights) {
|
void CElementGen::RenderModels() {
|
||||||
// Check to make sure our buffers are ready to render
|
|
||||||
// if (!x26c_31_LINE) { // && (!m_instBuf || !m_uniformBuf)
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// if (x28_loadedGenDesc->x45_24_x31_26_PMUS) { // && (!m_instBufPmus || !m_uniformBufPmus)
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
CParticleGlobals::instance()->m_particleAccessParameters = nullptr;
|
CParticleGlobals::instance()->m_particleAccessParameters = nullptr;
|
||||||
if (x26d_26_modelsUseLights) {
|
if (x26d_26_modelsUseLights) {
|
||||||
CGraphics::SetLightState(x274_backupLightActive);
|
CGraphics::SetLightState(x274_backupLightActive);
|
||||||
|
@ -959,29 +943,6 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
|
||||||
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::skPassThru);
|
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::skPassThru);
|
||||||
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
|
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch (m_shaderClass) {
|
|
||||||
// case CElementGenShaders::EShaderClass::Tex:
|
|
||||||
// g_instTexData.clear();
|
|
||||||
// g_instTexData.reserve(x30_particles.size());
|
|
||||||
// break;
|
|
||||||
// case CElementGenShaders::EShaderClass::NoTex:
|
|
||||||
// g_instNoTexData.clear();
|
|
||||||
// g_instNoTexData.reserve(x30_particles.size());
|
|
||||||
// break;
|
|
||||||
// default:
|
|
||||||
// Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class"));
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// SParticleUniforms uniformData = {CGraphics::GetPerspectiveProjectionMatrix(/*true*/), {1.f, 1.f, 1.f, 1.f}};
|
|
||||||
|
|
||||||
// m_uniformBufPmus->load(&uniformData, sizeof(SParticleUniforms));
|
|
||||||
//
|
|
||||||
// if (moveRedToAlphaBuffer)
|
|
||||||
// CGraphics::SetShaderDataBinding(m_redToAlphaDataBindPmus[g_Renderer->IsThermalVisorHotPass()]);
|
|
||||||
// else
|
|
||||||
// CGraphics::SetShaderDataBinding(m_normalDataBindPmus[g_Renderer->IsThermalVisorHotPass()]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zeus::CTransform orient = zeus::CTransform();
|
zeus::CTransform orient = zeus::CTransform();
|
||||||
|
@ -1122,6 +1083,7 @@ void CElementGen::RenderModels(const CActorLights* actorLights) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CGraphics::SetCullMode(ERglCullMode::Front);
|
CGraphics::SetCullMode(ERglCullMode::Front);
|
||||||
|
CTevCombiners::ResetStates();
|
||||||
if (moveRedToAlphaBuffer) {
|
if (moveRedToAlphaBuffer) {
|
||||||
GXSetTevSwapMode(GX::TEVSTAGE1, GX::TEV_SWAP0, GX::TEV_SWAP0);
|
GXSetTevSwapMode(GX::TEVSTAGE1, GX::TEV_SWAP0, GX::TEV_SWAP0);
|
||||||
}
|
}
|
||||||
|
@ -1231,9 +1193,7 @@ void CElementGen::RenderParticles() {
|
||||||
CGenDescription* desc = x1c_genDesc.GetObj();
|
CGenDescription* desc = x1c_genDesc.GetObj();
|
||||||
CGlobalRandom gr(x27c_randState);
|
CGlobalRandom gr(x27c_randState);
|
||||||
|
|
||||||
CUVElement* texr = desc->x54_x40_TEXR.get();
|
if (IsIndirectTextured()) {
|
||||||
CUVElement* tind = desc->x58_x44_TIND.get();
|
|
||||||
if (texr && tind) {
|
|
||||||
RenderParticlesIndirectTexture();
|
RenderParticlesIndirectTexture();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1249,6 +1209,8 @@ void CElementGen::RenderParticles() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasModuColor = x338_moduColor != zeus::skBlack; // TODO skClear?
|
||||||
|
CGraphics::SetCullMode(ERglCullMode::None);
|
||||||
zeus::CTransform systemModelMatrix(CGraphics::g_ViewMatrix);
|
zeus::CTransform systemModelMatrix(CGraphics::g_ViewMatrix);
|
||||||
systemModelMatrix.origin.zeroOut();
|
systemModelMatrix.origin.zeroOut();
|
||||||
zeus::CTransform systemCameraMatrix = systemModelMatrix.inverse() * x22c_globalOrientation;
|
zeus::CTransform systemCameraMatrix = systemModelMatrix.inverse() * x22c_globalOrientation;
|
||||||
|
@ -1260,32 +1222,116 @@ void CElementGen::RenderParticles() {
|
||||||
else
|
else
|
||||||
CGraphics::SetModelMatrix(systemModelMatrix);
|
CGraphics::SetModelMatrix(systemModelMatrix);
|
||||||
|
|
||||||
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
|
CGraphics::SetAlphaCompare(ERglAlphaFunc::Greater, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
|
||||||
|
|
||||||
SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f};
|
SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f};
|
||||||
bool constUVs = true;
|
bool constUVs = true;
|
||||||
CTexture* cachedTex = nullptr;
|
CTexture* cachedTex = nullptr;
|
||||||
|
|
||||||
// SParticleUniforms uniformData = {CGraphics::GetPerspectiveProjectionMatrix(/*true*/) *
|
auto* rota = x28_loadedGenDesc->x50_x3c_ROTA.get();
|
||||||
// CGraphics::g_GXModelView.toMatrix4f(),
|
bool noRota = rota == nullptr;
|
||||||
// {1.f, 1.f, 1.f, 1.f}};
|
if (rota != nullptr && rota->IsConstant()) {
|
||||||
|
float value = 1.f;
|
||||||
|
rota->GetValue(0, value);
|
||||||
|
if (value == 0.f) {
|
||||||
|
value = 1.f;
|
||||||
|
rota->GetValue(1, value);
|
||||||
|
if (value == 0.f) {
|
||||||
|
noRota = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (texr) {
|
auto* texr = x28_loadedGenDesc->x54_x40_TEXR.get();
|
||||||
|
if (texr != nullptr) {
|
||||||
CParticle& target = x30_particles[0];
|
CParticle& target = x30_particles[0];
|
||||||
int partFrame = x74_curFrame - target.x28_startFrame;
|
int partFrame = x74_curFrame - target.x28_startFrame;
|
||||||
cachedTex = texr->GetValueTexture(partFrame).GetObj();
|
cachedTex = texr->GetValueTexture(partFrame).GetObj();
|
||||||
cachedTex->Load(GX::TEXMAP0, EClampMode::Repeat);
|
cachedTex->Load(GX::TEXMAP0, EClampMode::Repeat);
|
||||||
|
|
||||||
if (x338_moduColor != zeus::skBlack) {
|
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc);
|
||||||
|
if (hasModuColor) {
|
||||||
/* Add RASC * PREVC pass for MODU color loaded into channel mat-color */
|
/* Add RASC * PREVC pass for MODU color loaded into channel mat-color */
|
||||||
// uniformData.moduColor = x338_moduColor;
|
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::sTevPass804bfe68);
|
||||||
|
} else {
|
||||||
|
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
|
||||||
}
|
}
|
||||||
|
|
||||||
texr->GetValueUV(partFrame, uvs);
|
texr->GetValueUV(partFrame, uvs);
|
||||||
constUVs = texr->HasConstantUV();
|
constUVs = texr->HasConstantUV();
|
||||||
|
} else {
|
||||||
|
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::skPassThru);
|
||||||
|
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms));
|
constexpr std::array vtxDescList{
|
||||||
|
GX::VtxDescList{GX::VA_POS, GX::DIRECT},
|
||||||
|
GX::VtxDescList{GX::VA_CLR0, GX::DIRECT},
|
||||||
|
GX::VtxDescList{GX::VA_TEX0, GX::DIRECT},
|
||||||
|
GX::VtxDescList{},
|
||||||
|
};
|
||||||
|
CGX::SetVtxDescv(vtxDescList.data());
|
||||||
|
GX::TevStageID nextStage;
|
||||||
|
if (hasModuColor) {
|
||||||
|
CGX::SetNumChans(2);
|
||||||
|
nextStage = GX::TEVSTAGE2;
|
||||||
|
CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR1A1);
|
||||||
|
CGX::SetChanAmbColor(CGX::EChannelId::Channel1, zeus::skBlack);
|
||||||
|
CGX::SetChanMatColor(CGX::EChannelId::Channel1, x338_moduColor);
|
||||||
|
CGX::SetChanCtrl(CGX::EChannelId::Channel1, {});
|
||||||
|
} else {
|
||||||
|
CGX::SetNumChans(1);
|
||||||
|
nextStage = GX::TEVSTAGE1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool moveRedToAlphaBuffer = sMoveRedToAlphaBuffer;
|
||||||
|
if (g_subtractBlend) {
|
||||||
|
CGraphics::SetDepthWriteMode(x26c_28_zTest, ERglEnum::LEqual, false);
|
||||||
|
CGX::SetBlendMode(GX::BM_SUBTRACT, GX::BL_ONE, GX::BL_ZERO, GX::LO_CLEAR);
|
||||||
|
if (moveRedToAlphaBuffer) {
|
||||||
|
CGX::SetTevColorIn(nextStage, GX::CC_ZERO, GX::CC_CPREV, GX::CC_APREV, GX::CC_ZERO);
|
||||||
|
CGX::SetTevAlphaIn(nextStage, GX::CA_ZERO, GX::CA_TEXA, GX::CA_APREV, GX::CA_ZERO);
|
||||||
|
CGX::SetStandardTevColorAlphaOp(nextStage);
|
||||||
|
CGX::SetTevOrder(nextStage, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL);
|
||||||
|
GXSetTevSwapMode(nextStage, GX::TEV_SWAP0, GX::TEV_SWAP1);
|
||||||
|
nextStage = GX::TevStageID(nextStage + 1);
|
||||||
|
}
|
||||||
|
} else if (moveRedToAlphaBuffer) {
|
||||||
|
CGraphics::SetDepthWriteMode(x26c_28_zTest, ERglEnum::LEqual, false);
|
||||||
|
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear);
|
||||||
|
CGX::SetTevColorIn(nextStage, GX::CC_ZERO, GX::CC_CPREV, GX::CC_APREV, GX::CC_ZERO);
|
||||||
|
CGX::SetTevAlphaIn(nextStage, GX::CA_ZERO, GX::CA_TEXA, GX::CA_APREV, GX::CA_ZERO);
|
||||||
|
CGX::SetStandardTevColorAlphaOp(nextStage);
|
||||||
|
CGX::SetTevOrder(nextStage, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL);
|
||||||
|
GXSetTevSwapMode(nextStage, GX::TEV_SWAP0, GX::TEV_SWAP1);
|
||||||
|
nextStage = GX::TevStageID(nextStage + 1);
|
||||||
|
} else if (x26c_26_AAPH) {
|
||||||
|
CGraphics::SetDepthWriteMode(x26c_28_zTest, ERglEnum::LEqual, false);
|
||||||
|
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear);
|
||||||
|
} else {
|
||||||
|
CGraphics::SetDepthWriteMode(x26c_28_zTest, ERglEnum::LEqual, x26c_27_ZBUF);
|
||||||
|
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha,
|
||||||
|
ERglLogicOp::Clear);
|
||||||
|
}
|
||||||
|
CGX::SetNumTevStages(nextStage);
|
||||||
|
CGX::SetNumTexGens(1);
|
||||||
|
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR0A0);
|
||||||
|
CGX::SetChanCtrl(CGX::EChannelId::Channel0, false, GX::SRC_REG, GX::SRC_VTX, {}, GX::DF_NONE, GX::AF_NONE);
|
||||||
|
CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY);
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT6, GX::VA_POS, GX::POS_XYZ, GX::F32, 0);
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT6, GX::VA_CLR0, GX::CLR_RGBA, GX::RGBA8, 0);
|
||||||
|
// if (constUVs) {
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT6, GX::VA_TEX0, GX::TEX_ST, GX::RGBA8, 1);
|
||||||
|
// } else {
|
||||||
|
// GXSetVtxAttrFmt(GX::VTXFMT6, GX::VA_TEX0, GX::TEX_ST, GX::F32, 0);
|
||||||
|
// }
|
||||||
|
|
||||||
|
int mbspVal = std::max(1, x270_MBSP);
|
||||||
|
if (x26c_30_MBLR) {
|
||||||
|
CGX::Begin(GX::QUADS, GX::VTXFMT6, mbspVal * x30_particles.size() * 4);
|
||||||
|
} else {
|
||||||
|
CGX::Begin(GX::QUADS, GX::VTXFMT6, mbspVal * 4);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<CParticleListItem> sortItems;
|
std::vector<CParticleListItem> sortItems;
|
||||||
if (desc->x44_28_x30_28_SORT) {
|
if (desc->x44_28_x30_28_SORT) {
|
||||||
|
@ -1304,70 +1350,21 @@ void CElementGen::RenderParticles() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool moveRedToAlphaBuffer = false;
|
|
||||||
if (sMoveRedToAlphaBuffer && x26c_26_AAPH)
|
|
||||||
moveRedToAlphaBuffer = true;
|
|
||||||
|
|
||||||
if (g_subtractBlend) {
|
|
||||||
// FIXME should there be NoTex specializations for RedToAlpha?
|
|
||||||
// if (moveRedToAlphaBuffer && desc->x54_x40_TEXR)
|
|
||||||
// CGraphics::SetShaderDataBinding(m_redToAlphaSubDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
|
||||||
// else
|
|
||||||
// CGraphics::SetShaderDataBinding(m_normalSubDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
|
||||||
} else {
|
|
||||||
// if (moveRedToAlphaBuffer && desc->x54_x40_TEXR)
|
|
||||||
// CGraphics::SetShaderDataBinding(m_redToAlphaDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
|
||||||
// else
|
|
||||||
// CGraphics::SetShaderDataBinding(m_normalDataBind[g_Renderer->IsThermalVisorHotPass()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
int mbspVal = std::max(1, x270_MBSP);
|
|
||||||
|
|
||||||
CParticleGlobals::instance()->SetEmitterTime(x74_curFrame);
|
CParticleGlobals::instance()->SetEmitterTime(x74_curFrame);
|
||||||
if (!x26c_30_MBLR) {
|
if (!x26c_30_MBLR) {
|
||||||
#if 0
|
if (!desc->x44_28_x30_28_SORT && constUVs && !x26c_29_ORNT) {
|
||||||
if (!desc->x44_28_x30_28_SORT && constUVs && !x26c_29_ORNT)
|
if (noRota) {
|
||||||
{
|
if (zeus::close_enough(x80_timeDeltaScale, 1.f)) {
|
||||||
if (!desc->x50_x3c_ROTA)
|
RenderBasicParticlesNoRotNoTS(systemCameraMatrix);
|
||||||
{
|
} else {
|
||||||
if (!zeus::close_enough(x80_timeDeltaScale, 1.f))
|
RenderBasicParticlesNoRotTS(systemCameraMatrix);
|
||||||
{
|
|
||||||
RenderBasicParticlesNoRotNoTS(systemCameraMatrix);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RenderBasicParticlesNoRotTS(systemCameraMatrix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!zeus::close_enough(x80_timeDeltaScale, 1.f))
|
|
||||||
{
|
|
||||||
RenderBasicParticlesRotNoTS(systemCameraMatrix);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RenderBasicParticlesRotTS(systemCameraMatrix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
} else if (zeus::close_enough(x80_timeDeltaScale, 1.f)) {
|
||||||
|
RenderBasicParticlesRotNoTS(systemCameraMatrix);
|
||||||
// switch (m_shaderClass) {
|
} else {
|
||||||
// case CElementGenShaders::EShaderClass::Tex:
|
RenderBasicParticlesRotTS(systemCameraMatrix);
|
||||||
// g_instTexData.clear();
|
}
|
||||||
// g_instTexData.reserve(x30_particles.size());
|
} else if (!x26c_29_ORNT) {
|
||||||
// break;
|
|
||||||
// case CElementGenShaders::EShaderClass::NoTex:
|
|
||||||
// g_instNoTexData.clear();
|
|
||||||
// g_instNoTexData.reserve(x30_particles.size());
|
|
||||||
// break;
|
|
||||||
// default:
|
|
||||||
// Log.report(logvisor::Fatal, FMT_STRING("unexpected particle shader class"));
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (!x26c_29_ORNT) {
|
|
||||||
for (size_t i = 0; i < x30_particles.size(); ++i) {
|
for (size_t i = 0; i < x30_particles.size(); ++i) {
|
||||||
const int partIdx = desc->x44_28_x30_28_SORT ? sortItems[i].x0_partIdx : int(i);
|
const int partIdx = desc->x44_28_x30_28_SORT ? sortItems[i].x0_partIdx : int(i);
|
||||||
CParticle& particle = x30_particles[partIdx];
|
CParticle& particle = x30_particles[partIdx];
|
||||||
|
@ -1382,75 +1379,42 @@ void CElementGen::RenderParticles() {
|
||||||
((particle.x4_pos - particle.x10_prevPos) * x80_timeDeltaScale + particle.x10_prevPos);
|
((particle.x4_pos - particle.x10_prevPos) * x80_timeDeltaScale + particle.x10_prevPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const float size = 0.5f * particle.x2c_lineLengthOrSize;
|
||||||
if (!constUVs) {
|
if (!constUVs) {
|
||||||
CParticleGlobals::instance()->SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame);
|
CParticleGlobals::instance()->SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame);
|
||||||
CParticleGlobals::instance()->UpdateParticleLifetimeTweenValues(partFrame);
|
CParticleGlobals::instance()->UpdateParticleLifetimeTweenValues(partFrame);
|
||||||
texr->GetValueUV(partFrame, uvs);
|
texr->GetValueUV(partFrame, uvs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const float size = 0.5f * particle.x2c_lineLengthOrSize;
|
if (noRota) {
|
||||||
if (0.f == particle.x30_lineWidthOrRota) {
|
GXPosition3f32(viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size);
|
||||||
// switch (m_shaderClass) {
|
GXColor4f32(particle.x34_color);
|
||||||
// case CElementGenShaders::EShaderClass::Tex: {
|
GXTexCoord2f32(uvs.xMax, uvs.yMax);
|
||||||
// SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
GXPosition3f32(viewPoint.x() - size, viewPoint.y(), viewPoint.z() + size);
|
||||||
// inst.pos[0] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
GXColor4f32(particle.x34_color);
|
||||||
// inst.pos[1] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
GXTexCoord2f32(uvs.xMin, uvs.yMax);
|
||||||
// inst.pos[2] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
GXPosition3f32(viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size);
|
||||||
// inst.pos[3] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
GXColor4f32(particle.x34_color);
|
||||||
// inst.color = particle.x34_color;
|
GXTexCoord2f32(uvs.xMin, uvs.yMin);
|
||||||
// inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
GXPosition3f32(viewPoint.x() + size, viewPoint.y(), viewPoint.z() - size);
|
||||||
// inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
GXColor4f32(particle.x34_color);
|
||||||
// inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
GXTexCoord2f32(uvs.xMax, uvs.yMin);
|
||||||
// inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case CElementGenShaders::EShaderClass::NoTex: {
|
|
||||||
// SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
|
||||||
// inst.pos[0] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
|
||||||
// inst.pos[1] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() + size, 1.f};
|
|
||||||
// inst.pos[2] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
|
||||||
// inst.pos[3] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size, 1.f};
|
|
||||||
// inst.color = particle.x34_color;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// default:
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
} else {
|
} else {
|
||||||
float theta = zeus::degToRad(particle.x30_lineWidthOrRota);
|
const float theta = zeus::degToRad(particle.x30_lineWidthOrRota);
|
||||||
float sinT = std::sin(theta) * size;
|
const float sinT = std::sin(theta) * size;
|
||||||
float cosT = std::cos(theta) * size;
|
const float cosT = std::cos(theta) * size;
|
||||||
|
GXPosition3f32(viewPoint.x() + (sinT + cosT), viewPoint.y(), viewPoint.z() + (cosT - sinT));
|
||||||
// switch (m_shaderClass) {
|
GXColor4f32(particle.x34_color);
|
||||||
// case CElementGenShaders::EShaderClass::Tex: {
|
GXTexCoord2f32(uvs.xMax, uvs.yMax);
|
||||||
// SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
GXPosition3f32(viewPoint.x() + (sinT - cosT), viewPoint.y(), viewPoint.z() + (sinT + cosT));
|
||||||
// inst.pos[0] = zeus::CVector4f{viewPoint.x() + sinT + cosT, viewPoint.y(), viewPoint.z() + cosT - sinT, 1.f};
|
GXColor4f32(particle.x34_color);
|
||||||
// inst.pos[1] = zeus::CVector4f{viewPoint.x() + sinT - cosT, viewPoint.y(), viewPoint.z() + sinT + cosT, 1.f};
|
GXTexCoord2f32(uvs.xMin, uvs.yMax);
|
||||||
// inst.pos[2] =
|
GXPosition3f32(viewPoint.x() - (sinT + cosT), viewPoint.y(), viewPoint.z() - (cosT - sinT));
|
||||||
// zeus::CVector4f{viewPoint.x() + (cosT - sinT), viewPoint.y(), viewPoint.z() + (-cosT - sinT), 1.f};
|
GXColor4f32(particle.x34_color);
|
||||||
// inst.pos[3] =
|
GXTexCoord2f32(uvs.xMin, uvs.yMin);
|
||||||
// zeus::CVector4f{viewPoint.x() - (sinT + cosT), viewPoint.y(), viewPoint.z() - (cosT - sinT), 1.f};
|
GXPosition3f32(viewPoint.x() + (-sinT + cosT), viewPoint.y(), viewPoint.z() + (-cosT - sinT));
|
||||||
// inst.color = particle.x34_color;
|
GXColor4f32(particle.x34_color);
|
||||||
// inst.uvs[0] = {uvs.xMax, uvs.yMax};
|
GXTexCoord2f32(uvs.xMax, uvs.yMin);
|
||||||
// inst.uvs[1] = {uvs.xMin, uvs.yMax};
|
|
||||||
// inst.uvs[2] = {uvs.xMax, uvs.yMin};
|
|
||||||
// inst.uvs[3] = {uvs.xMin, uvs.yMin};
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case CElementGenShaders::EShaderClass::NoTex: {
|
|
||||||
// SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
|
||||||
// inst.pos[0] = zeus::CVector4f{viewPoint.x() + sinT + cosT, viewPoint.y(), viewPoint.z() + cosT - sinT, 1.f};
|
|
||||||
// inst.pos[1] = zeus::CVector4f{viewPoint.x() + sinT - cosT, viewPoint.y(), viewPoint.z() + sinT + cosT, 1.f};
|
|
||||||
// inst.pos[2] =
|
|
||||||
// zeus::CVector4f{viewPoint.x() + (cosT - sinT), viewPoint.y(), viewPoint.z() + (-cosT - sinT), 1.f};
|
|
||||||
// inst.pos[3] =
|
|
||||||
// zeus::CVector4f{viewPoint.x() - (sinT + cosT), viewPoint.y(), viewPoint.z() - (cosT - sinT), 1.f};
|
|
||||||
// inst.color = particle.x34_color;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// default:
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1656,6 +1620,8 @@ void CElementGen::RenderParticles() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CGraphics::SetCullMode(ERglCullMode::Front);
|
||||||
|
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CElementGen::RenderParticlesIndirectTexture() {
|
void CElementGen::RenderParticlesIndirectTexture() {
|
||||||
|
@ -1965,4 +1931,85 @@ void CElementGen::Reset() {
|
||||||
|
|
||||||
void CElementGen::SetMoveRedToAlphaBuffer(bool move) { sMoveRedToAlphaBuffer = move; }
|
void CElementGen::SetMoveRedToAlphaBuffer(bool move) { sMoveRedToAlphaBuffer = move; }
|
||||||
|
|
||||||
|
void CElementGen::RenderBasicParticlesNoRotNoTS(const zeus::CTransform& xf) noexcept {
|
||||||
|
for (const auto& particle : x30_particles) {
|
||||||
|
const auto pos = xf * particle.x4_pos;
|
||||||
|
const auto size = 0.5f * particle.x2c_lineLengthOrSize;
|
||||||
|
GXPosition3f32(pos.x() + size, pos.y(), pos.z() + size);
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(1.f, 1.f);
|
||||||
|
GXPosition3f32(pos.x() - size, pos.y(), pos.z() + size);
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(0.f, 1.f);
|
||||||
|
GXPosition3f32(pos.x() - size, pos.y(), pos.z() - size);
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(0.f, 0.f);
|
||||||
|
GXPosition3f32(pos.x() + size, pos.y(), pos.z() - size);
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(1.f, 0.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CElementGen::RenderBasicParticlesNoRotTS(const zeus::CTransform& xf) noexcept {
|
||||||
|
for (const auto& particle : x30_particles) {
|
||||||
|
const auto pos = xf * (x80_timeDeltaScale * (particle.x4_pos - particle.x10_prevPos) + particle.x10_prevPos);
|
||||||
|
const auto size = 0.5f * particle.x2c_lineLengthOrSize;
|
||||||
|
GXPosition3f32(pos.x() + size, pos.y(), pos.z() + size);
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(1.f, 1.f);
|
||||||
|
GXPosition3f32(pos.x() - size, pos.y(), pos.z() + size);
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(0.f, 1.f);
|
||||||
|
GXPosition3f32(pos.x() - size, pos.y(), pos.z() - size);
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(0.f, 0.f);
|
||||||
|
GXPosition3f32(pos.x() + size, pos.y(), pos.z() - size);
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(1.f, 0.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CElementGen::RenderBasicParticlesRotNoTS(const zeus::CTransform& xf) noexcept {
|
||||||
|
for (const auto& particle : x30_particles) {
|
||||||
|
const auto pos = xf * particle.x4_pos;
|
||||||
|
const auto size = 0.5f * particle.x2c_lineLengthOrSize;
|
||||||
|
const float theta = zeus::degToRad(particle.x30_lineWidthOrRota);
|
||||||
|
const float sinT = std::sin(theta) * size;
|
||||||
|
const float cosT = std::cos(theta) * size;
|
||||||
|
GXPosition3f32(pos.x() + (sinT + cosT), pos.y(), pos.z() + (cosT - sinT));
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(1.f, 1.f);
|
||||||
|
GXPosition3f32(pos.x() + (sinT - cosT), pos.y(), pos.z() + (sinT + cosT));
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(0.f, 1.f);
|
||||||
|
GXPosition3f32(pos.x() - (sinT + cosT), pos.y(), pos.z() - (cosT - sinT));
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(0.f, 0.f);
|
||||||
|
GXPosition3f32(pos.x() + (-sinT + cosT), pos.y(), pos.z() + (-cosT - sinT));
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(1.f, 0.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CElementGen::RenderBasicParticlesRotTS(const zeus::CTransform& xf) noexcept {
|
||||||
|
for (const auto& particle : x30_particles) {
|
||||||
|
const auto pos = xf * (x80_timeDeltaScale * (particle.x4_pos - particle.x10_prevPos) + particle.x10_prevPos);
|
||||||
|
const auto size = 0.5f * particle.x2c_lineLengthOrSize;
|
||||||
|
const float theta = zeus::degToRad(particle.x30_lineWidthOrRota);
|
||||||
|
const float sinT = std::sin(theta) * size;
|
||||||
|
const float cosT = std::cos(theta) * size;
|
||||||
|
GXPosition3f32(pos.x() + (sinT + cosT), pos.y(), pos.z() + (cosT - sinT));
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(1.f, 1.f);
|
||||||
|
GXPosition3f32(pos.x() + (sinT - cosT), pos.y(), pos.z() + (sinT + cosT));
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(0.f, 1.f);
|
||||||
|
GXPosition3f32(pos.x() - (sinT + cosT), pos.y(), pos.z() - (cosT - sinT));
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(0.f, 0.f);
|
||||||
|
GXPosition3f32(pos.x() + (-sinT + cosT), pos.y(), pos.z() + (-cosT - sinT));
|
||||||
|
GXColor4f32(particle.x34_color);
|
||||||
|
GXTexCoord2f32(1.f, 0.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace metaforce
|
} // namespace metaforce
|
||||||
|
|
|
@ -184,13 +184,13 @@ public:
|
||||||
void SetExternalVar(int index, float var) { x9c_externalVars[index] = var; }
|
void SetExternalVar(int index, float var) { x9c_externalVars[index] = var; }
|
||||||
|
|
||||||
bool InternalUpdate(double dt);
|
bool InternalUpdate(double dt);
|
||||||
void RenderModels(const CActorLights* actLights);
|
void RenderModels();
|
||||||
void RenderLines();
|
void RenderLines();
|
||||||
void RenderParticles();
|
void RenderParticles();
|
||||||
void RenderParticlesIndirectTexture();
|
void RenderParticlesIndirectTexture();
|
||||||
|
|
||||||
bool Update(double t) override;
|
bool Update(double t) override;
|
||||||
void Render(const CActorLights* actorLights = nullptr) override;
|
void Render() override;
|
||||||
void SetOrientation(const zeus::CTransform& orientation) override;
|
void SetOrientation(const zeus::CTransform& orientation) override;
|
||||||
void SetTranslation(const zeus::CVector3f& translation) override;
|
void SetTranslation(const zeus::CVector3f& translation) override;
|
||||||
void SetGlobalOrientation(const zeus::CTransform& orientation) override;
|
void SetGlobalOrientation(const zeus::CTransform& orientation) override;
|
||||||
|
@ -228,6 +228,12 @@ public:
|
||||||
|
|
||||||
std::vector<CParticle> const& GetParticles() const { return x30_particles; }
|
std::vector<CParticle> const& GetParticles() const { return x30_particles; }
|
||||||
std::vector<CParticle>& GetParticles() { return x30_particles; }
|
std::vector<CParticle>& GetParticles() { return x30_particles; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void RenderBasicParticlesNoRotNoTS(const zeus::CTransform& xf) noexcept;
|
||||||
|
void RenderBasicParticlesNoRotTS(const zeus::CTransform& xf) noexcept;
|
||||||
|
void RenderBasicParticlesRotNoTS(const zeus::CTransform& xf) noexcept;
|
||||||
|
void RenderBasicParticlesRotTS(const zeus::CTransform& xf) noexcept;
|
||||||
};
|
};
|
||||||
ENABLE_BITWISE_ENUM(CElementGen::EOptionalSystemFlags)
|
ENABLE_BITWISE_ENUM(CElementGen::EOptionalSystemFlags)
|
||||||
|
|
||||||
|
|
|
@ -78,30 +78,51 @@ SElectricGeneratorDesc CParticleDataFactory::GetElectricGeneratorDesc(CInputStre
|
||||||
return resPool->GetObj({FOURCC('ELSC'), id});
|
return resPool->GetObj({FOURCC('ELSC'), id});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<CTexture> CreateTexture(u32 value) {
|
||||||
|
auto tex = std::make_unique<CTexture>(ETexelFormat::RGBA8, 4, 4, 1, "CUVElement Fallback Texture"sv);
|
||||||
|
auto* data = reinterpret_cast<u32*>(tex->Lock());
|
||||||
|
for (int i = 0; i < 4 * 4; ++i) {
|
||||||
|
data[i] = value;
|
||||||
|
}
|
||||||
|
tex->UnLock();
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<CUVElement> CParticleDataFactory::GetTextureElement(CInputStream& in, CSimplePool* resPool) {
|
std::unique_ptr<CUVElement> CParticleDataFactory::GetTextureElement(CInputStream& in, CSimplePool* resPool) {
|
||||||
FourCC clsId = GetClassID(in);
|
FourCC clsId = GetClassID(in);
|
||||||
switch (clsId.toUint32()) {
|
switch (clsId.toUint32()) {
|
||||||
case SBIG('CNST'): {
|
case SBIG('CNST'): {
|
||||||
FourCC subId = GetClassID(in);
|
CAssetId id;
|
||||||
if (subId == SBIG('NONE'))
|
const auto subId = GetClassID(in);
|
||||||
return nullptr;
|
if (subId != SBIG('NONE')) {
|
||||||
CAssetId id = in.Get<CAssetId>();
|
id = in.Get<CAssetId>();
|
||||||
TToken<CTexture> txtr = resPool->GetObj({FOURCC('TXTR'), id});
|
}
|
||||||
|
TToken<CTexture> txtr;
|
||||||
|
if (id.IsValid()) {
|
||||||
|
txtr = resPool->GetObj({FOURCC('TXTR'), id});
|
||||||
|
} else {
|
||||||
|
txtr = CreateTexture(0xFFFFFFFF);
|
||||||
|
}
|
||||||
return std::make_unique<CUVEConstant>(std::move(txtr));
|
return std::make_unique<CUVEConstant>(std::move(txtr));
|
||||||
}
|
}
|
||||||
case SBIG('ATEX'): {
|
case SBIG('ATEX'): {
|
||||||
const FourCC subId = GetClassID(in);
|
CAssetId id;
|
||||||
if (subId == SBIG('NONE')) {
|
const auto subId = GetClassID(in);
|
||||||
return nullptr;
|
if (subId != SBIG('NONE')) {
|
||||||
|
id = in.Get<CAssetId>();
|
||||||
}
|
}
|
||||||
const CAssetId id = in.Get<CAssetId>();
|
|
||||||
auto a = GetIntElement(in);
|
auto a = GetIntElement(in);
|
||||||
auto b = GetIntElement(in);
|
auto b = GetIntElement(in);
|
||||||
auto c = GetIntElement(in);
|
auto c = GetIntElement(in);
|
||||||
auto d = GetIntElement(in);
|
auto d = GetIntElement(in);
|
||||||
auto e = GetIntElement(in);
|
auto e = GetIntElement(in);
|
||||||
const bool f = GetBool(in);
|
const bool f = GetBool(in);
|
||||||
TToken<CTexture> txtr = resPool->GetObj({FOURCC('TXTR'), id});
|
TToken<CTexture> txtr;
|
||||||
|
if (id.IsValid()) {
|
||||||
|
txtr = resPool->GetObj({FOURCC('TXTR'), id});
|
||||||
|
} else {
|
||||||
|
txtr = CreateTexture(0xFFFFFFFF);
|
||||||
|
}
|
||||||
return std::make_unique<CUVEAnimTexture>(std::move(txtr), std::move(std::move(a)), std::move(b), std::move(c),
|
return std::make_unique<CUVEAnimTexture>(std::move(txtr), std::move(std::move(a)), std::move(b), std::move(c),
|
||||||
std::move(d), std::move(e), f);
|
std::move(d), std::move(e), f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -607,7 +607,7 @@ bool CParticleElectric::Update(double dt) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CParticleElectric::Render(const CActorLights* lights) {
|
void CParticleElectric::Render() {
|
||||||
SCOPED_GRAPHICS_DEBUG_GROUP(
|
SCOPED_GRAPHICS_DEBUG_GROUP(
|
||||||
fmt::format(FMT_STRING("CParticleElectric::Render {}"), *x1c_elecDesc.GetObjectTag()).c_str(), zeus::skYellow);
|
fmt::format(FMT_STRING("CParticleElectric::Render {}"), *x1c_elecDesc.GetObjectTag()).c_str(), zeus::skYellow);
|
||||||
|
|
||||||
|
@ -625,13 +625,13 @@ void CParticleElectric::Render(const CActorLights* lights) {
|
||||||
|
|
||||||
if (x450_25_haveGPSM) {
|
if (x450_25_haveGPSM) {
|
||||||
for (int i = 0; i < x154_SCNT; ++i) {
|
for (int i = 0; i < x154_SCNT; ++i) {
|
||||||
x400_gpsmGenerators[i]->Render(lights);
|
x400_gpsmGenerators[i]->Render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x450_26_haveEPSM) {
|
if (x450_26_haveEPSM) {
|
||||||
for (int i = 0; i < x154_SCNT; ++i) {
|
for (int i = 0; i < x154_SCNT; ++i) {
|
||||||
x410_epsmGenerators[i]->Render(lights);
|
x410_epsmGenerators[i]->Render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ public:
|
||||||
explicit CParticleElectric(const TToken<CElectricDescription>& desc);
|
explicit CParticleElectric(const TToken<CElectricDescription>& desc);
|
||||||
|
|
||||||
bool Update(double) override;
|
bool Update(double) override;
|
||||||
void Render(const CActorLights* lights = nullptr) override;
|
void Render() override;
|
||||||
void SetOrientation(const zeus::CTransform& orientation) override;
|
void SetOrientation(const zeus::CTransform& orientation) override;
|
||||||
void SetTranslation(const zeus::CVector3f& translation) override;
|
void SetTranslation(const zeus::CVector3f& translation) override;
|
||||||
void SetGlobalOrientation(const zeus::CTransform& orientation) override;
|
void SetGlobalOrientation(const zeus::CTransform& orientation) override;
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
virtual ~CParticleGen() = default;
|
virtual ~CParticleGen() = default;
|
||||||
|
|
||||||
virtual bool Update(double) = 0;
|
virtual bool Update(double) = 0;
|
||||||
virtual void Render(const CActorLights* = nullptr) = 0;
|
virtual void Render() = 0;
|
||||||
virtual void SetOrientation(const zeus::CTransform&) = 0;
|
virtual void SetOrientation(const zeus::CTransform&) = 0;
|
||||||
virtual void SetTranslation(const zeus::CVector3f&) = 0;
|
virtual void SetTranslation(const zeus::CVector3f&) = 0;
|
||||||
virtual void SetGlobalOrientation(const zeus::CTransform&) = 0;
|
virtual void SetGlobalOrientation(const zeus::CTransform&) = 0;
|
||||||
|
|
|
@ -928,7 +928,7 @@ void CParticleSwoosh::Render2SidedNoSplineNoGaps() {
|
||||||
// CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart);
|
// CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CParticleSwoosh::Render(const CActorLights*) {
|
void CParticleSwoosh::Render() {
|
||||||
if (x1b4_LENG < 2 || x1ac_particleCount <= 1) {
|
if (x1b4_LENG < 2 || x1ac_particleCount <= 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@ public:
|
||||||
CSwooshDescription* GetDesc() { return x1c_desc.GetObj(); }
|
CSwooshDescription* GetDesc() { return x1c_desc.GetObj(); }
|
||||||
|
|
||||||
bool Update(double) override;
|
bool Update(double) override;
|
||||||
void Render(const CActorLights* = nullptr) override;
|
void Render() override;
|
||||||
void SetOrientation(const zeus::CTransform&) override;
|
void SetOrientation(const zeus::CTransform&) override;
|
||||||
void SetTranslation(const zeus::CVector3f&) override;
|
void SetTranslation(const zeus::CVector3f&) override;
|
||||||
void SetGlobalOrientation(const zeus::CTransform&) override;
|
void SetGlobalOrientation(const zeus::CTransform&) override;
|
||||||
|
|
|
@ -241,9 +241,9 @@ void CWaveBuster::RenderParticles() {
|
||||||
}
|
}
|
||||||
|
|
||||||
x38c_busterSparksGen->SetParticleEmission(false);
|
x38c_busterSparksGen->SetParticleEmission(false);
|
||||||
x384_busterSwoosh1Gen->Render(GetActorLights());
|
x384_busterSwoosh1Gen->Render();
|
||||||
x388_busterSwoosh2Gen->Render(GetActorLights());
|
x388_busterSwoosh2Gen->Render();
|
||||||
x38c_busterSparksGen->Render(GetActorLights());
|
x38c_busterSparksGen->Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWaveBuster::RenderBeam() {
|
void CWaveBuster::RenderBeam() {
|
||||||
|
|
|
@ -525,8 +525,8 @@ float CActor::GetPitch() const { return zeus::CQuaternion(x34_transform.buildMat
|
||||||
float CActor::GetYaw() const { return zeus::CQuaternion(x34_transform.buildMatrix3f()).yaw(); }
|
float CActor::GetYaw() const { return zeus::CQuaternion(x34_transform.buildMatrix3f()).yaw(); }
|
||||||
|
|
||||||
void CActor::EnsureRendered(const CStateManager& mgr) {
|
void CActor::EnsureRendered(const CStateManager& mgr) {
|
||||||
const zeus::CAABox aabb = GetSortingBounds(mgr);
|
const auto bounds = GetSortingBounds(mgr);
|
||||||
EnsureRendered(mgr, aabb.closestPointAlongVector(CGraphics::g_ViewMatrix.basis[1]), aabb);
|
EnsureRendered(mgr, bounds.closestPointAlongVector(CGraphics::g_ViewMatrix.frontVector()), bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CActor::EnsureRendered(const CStateManager& stateMgr, const zeus::CVector3f& pos, const zeus::CAABox& aabb) {
|
void CActor::EnsureRendered(const CStateManager& stateMgr, const zeus::CVector3f& pos, const zeus::CAABox& aabb) {
|
||||||
|
|
|
@ -249,18 +249,16 @@ void CScriptEffect::AddToRenderer(const zeus::CFrustum& frustum, CStateManager&
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScriptEffect::Render(CStateManager& mgr) {
|
void CScriptEffect::Render(CStateManager& mgr) {
|
||||||
/* The following code is kept for reference, this is now performed in CElementGen
|
if (x138_actorLights) {
|
||||||
if (x138_actorLights)
|
x138_actorLights->ActivateLights();
|
||||||
x138_actorLights->ActivateLights();
|
}
|
||||||
*/
|
|
||||||
if (x104_particleSystem && x104_particleSystem->GetParticleCountAll() > 0) {
|
if (x104_particleSystem && x104_particleSystem->GetParticleCountAll() > 0) {
|
||||||
g_NumParticlesRendered += x104_particleSystem->GetParticleCountAll();
|
g_NumParticlesRendered += x104_particleSystem->GetParticleCountAll();
|
||||||
x104_particleSystem->Render(x138_actorLights.get());
|
x104_particleSystem->Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xf4_electric && xf4_electric->GetParticleCount() > 0) {
|
if (xf4_electric && xf4_electric->GetParticleCount() > 0) {
|
||||||
g_NumParticlesRendered += xf4_electric->GetParticleCount();
|
g_NumParticlesRendered += xf4_electric->GetParticleCount();
|
||||||
xf4_electric->Render(x138_actorLights.get());
|
xf4_electric->Render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,14 +346,12 @@ void CScriptEffect::CalculateRenderBounds() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (particleBounds || electricBounds) {
|
if (particleBounds || electricBounds) {
|
||||||
zeus::CAABox renderBounds = zeus::CAABox();
|
zeus::CAABox renderBounds;
|
||||||
if (particleBounds) {
|
if (particleBounds) {
|
||||||
renderBounds.accumulateBounds(particleBounds->min);
|
renderBounds.accumulateBounds(*particleBounds);
|
||||||
renderBounds.accumulateBounds(particleBounds->max);
|
|
||||||
}
|
}
|
||||||
if (electricBounds) {
|
if (electricBounds) {
|
||||||
renderBounds.accumulateBounds(electricBounds->min);
|
renderBounds.accumulateBounds(*electricBounds);
|
||||||
renderBounds.accumulateBounds(electricBounds->max);
|
|
||||||
}
|
}
|
||||||
x9c_renderBounds = renderBounds;
|
x9c_renderBounds = renderBounds;
|
||||||
x111_26_canRender = true;
|
x111_26_canRender = true;
|
||||||
|
|
|
@ -510,30 +510,30 @@ void CScriptGunTurret::Render(CStateManager& mgr) {
|
||||||
case ETurretState::DeactiveFromReady:
|
case ETurretState::DeactiveFromReady:
|
||||||
case ETurretState::Deactivating:
|
case ETurretState::Deactivating:
|
||||||
case ETurretState::DeactivatingFromReady:
|
case ETurretState::DeactivatingFromReady:
|
||||||
x470_deactivateLight->Render(x90_actorLights.get());
|
x470_deactivateLight->Render();
|
||||||
break;
|
break;
|
||||||
case ETurretState::Inactive:
|
case ETurretState::Inactive:
|
||||||
x468_idleLight->Render(x90_actorLights.get());
|
x468_idleLight->Render();
|
||||||
break;
|
break;
|
||||||
case ETurretState::PanningA:
|
case ETurretState::PanningA:
|
||||||
case ETurretState::PanningB:
|
case ETurretState::PanningB:
|
||||||
x490_panningEffect->Render(x90_actorLights.get());
|
x490_panningEffect->Render();
|
||||||
break;
|
break;
|
||||||
case ETurretState::Ready:
|
case ETurretState::Ready:
|
||||||
case ETurretState::Targeting:
|
case ETurretState::Targeting:
|
||||||
case ETurretState::Firing:
|
case ETurretState::Firing:
|
||||||
case ETurretState::ExitTargeting:
|
case ETurretState::ExitTargeting:
|
||||||
case ETurretState::Frenzy:
|
case ETurretState::Frenzy:
|
||||||
x478_targettingLight->Render(x90_actorLights.get());
|
x478_targettingLight->Render();
|
||||||
if (x520_state == ETurretState::Firing) {
|
if (x520_state == ETurretState::Firing) {
|
||||||
x488_chargingEffect->Render(x90_actorLights.get());
|
x488_chargingEffect->Render();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
x480_frozenEffect->Render(x90_actorLights.get());
|
x480_frozenEffect->Render();
|
||||||
}
|
}
|
||||||
} else if (x258_type == ETurretComponent::Base) {
|
} else if (x258_type == ETurretComponent::Base) {
|
||||||
if (x4a4_extensionModel && x4f8_extensionT > 0.f) {
|
if (x4a4_extensionModel && x4f8_extensionT > 0.f) {
|
||||||
|
|
|
@ -191,6 +191,7 @@ inline void xxh3_update(XXH3_state_t& state, const wgpu::SamplerDescriptor& inpu
|
||||||
namespace aurora::gfx {
|
namespace aurora::gfx {
|
||||||
using NewPipelineCallback = std::function<wgpu::RenderPipeline()>;
|
using NewPipelineCallback = std::function<wgpu::RenderPipeline()>;
|
||||||
std::mutex g_pipelineMutex;
|
std::mutex g_pipelineMutex;
|
||||||
|
static bool g_hasPipelineThread = false;
|
||||||
static std::thread g_pipelineThread;
|
static std::thread g_pipelineThread;
|
||||||
static std::atomic_bool g_pipelineThreadEnd;
|
static std::atomic_bool g_pipelineThreadEnd;
|
||||||
static std::condition_variable g_pipelineCv;
|
static std::condition_variable g_pipelineCv;
|
||||||
|
@ -225,9 +226,14 @@ static PipelineRef find_pipeline(PipelineCreateCommand command, NewPipelineCallb
|
||||||
std::scoped_lock guard{g_pipelineMutex};
|
std::scoped_lock guard{g_pipelineMutex};
|
||||||
found = g_pipelines.contains(hash);
|
found = g_pipelines.contains(hash);
|
||||||
if (!found) {
|
if (!found) {
|
||||||
const auto ref =
|
if (g_hasPipelineThread) {
|
||||||
std::find_if(g_queuedPipelines.begin(), g_queuedPipelines.end(), [=](auto v) { return v.first == hash; });
|
const auto ref =
|
||||||
if (ref != g_queuedPipelines.end()) {
|
std::find_if(g_queuedPipelines.begin(), g_queuedPipelines.end(), [=](auto v) { return v.first == hash; });
|
||||||
|
if (ref != g_queuedPipelines.end()) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g_pipelines.try_emplace(hash, cb());
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -387,7 +393,11 @@ static void pipeline_worker() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize() {
|
void initialize() {
|
||||||
g_pipelineThread = std::thread(pipeline_worker);
|
// No async pipelines for OpenGL (ES)
|
||||||
|
if (gpu::g_backendType != wgpu::BackendType::OpenGL && gpu::g_backendType != wgpu::BackendType::OpenGLES) {
|
||||||
|
g_pipelineThread = std::thread(pipeline_worker);
|
||||||
|
g_hasPipelineThread = true;
|
||||||
|
}
|
||||||
|
|
||||||
const auto createBuffer = [](wgpu::Buffer& out, wgpu::BufferUsage usage, uint64_t size, const char* label) {
|
const auto createBuffer = [](wgpu::Buffer& out, wgpu::BufferUsage usage, uint64_t size, const char* label) {
|
||||||
const wgpu::BufferDescriptor descriptor{
|
const wgpu::BufferDescriptor descriptor{
|
||||||
|
@ -419,9 +429,11 @@ void initialize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void shutdown() {
|
void shutdown() {
|
||||||
g_pipelineThreadEnd = true;
|
if (g_hasPipelineThread) {
|
||||||
g_pipelineCv.notify_all();
|
g_pipelineThreadEnd = true;
|
||||||
g_pipelineThread.join();
|
g_pipelineCv.notify_all();
|
||||||
|
g_pipelineThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
gx::shutdown();
|
gx::shutdown();
|
||||||
|
|
||||||
|
|
|
@ -282,37 +282,93 @@ static inline wgpu::CompareFunction to_compare_function(GX::Compare func) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline wgpu::BlendState to_blend_state(GX::BlendMode mode, GX::BlendFactor srcFac, GX::BlendFactor dstFac,
|
static inline wgpu::BlendState to_blend_state(GX::BlendMode mode, GX::BlendFactor srcFac, GX::BlendFactor dstFac,
|
||||||
std::optional<float> dstAlpha) {
|
GX::LogicOp op, std::optional<float> dstAlpha) {
|
||||||
wgpu::BlendComponent colorBlendComponent;
|
wgpu::BlendComponent colorBlendComponent;
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
|
case GX::BM_NONE:
|
||||||
|
colorBlendComponent = {
|
||||||
|
.operation = wgpu::BlendOperation::Add,
|
||||||
|
.srcFactor = wgpu::BlendFactor::Src,
|
||||||
|
.dstFactor = wgpu::BlendFactor::Zero,
|
||||||
|
};
|
||||||
|
break;
|
||||||
case GX::BM_BLEND:
|
case GX::BM_BLEND:
|
||||||
colorBlendComponent = {
|
colorBlendComponent = {
|
||||||
.operation = wgpu::BlendOperation::Add,
|
.operation = wgpu::BlendOperation::Add,
|
||||||
.srcFactor = to_blend_factor(srcFac),
|
.srcFactor = to_blend_factor(srcFac),
|
||||||
.dstFactor = to_blend_factor(dstFac),
|
.dstFactor = to_blend_factor(dstFac),
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case GX::BM_SUBTRACT:
|
case GX::BM_SUBTRACT:
|
||||||
colorBlendComponent = {
|
colorBlendComponent = {
|
||||||
.operation = wgpu::BlendOperation::Subtract,
|
.operation = wgpu::BlendOperation::ReverseSubtract,
|
||||||
.srcFactor = wgpu::BlendFactor::Src,
|
.srcFactor = wgpu::BlendFactor::Src,
|
||||||
.dstFactor = wgpu::BlendFactor::Dst,
|
.dstFactor = wgpu::BlendFactor::Dst,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
case GX::BM_LOGIC:
|
||||||
|
switch (op) {
|
||||||
|
case GX::LO_CLEAR:
|
||||||
|
colorBlendComponent = {
|
||||||
|
.operation = wgpu::BlendOperation::Add,
|
||||||
|
.srcFactor = wgpu::BlendFactor::Zero,
|
||||||
|
.dstFactor = wgpu::BlendFactor::Zero,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case GX::LO_COPY:
|
||||||
|
colorBlendComponent = {
|
||||||
|
.operation = wgpu::BlendOperation::Add,
|
||||||
|
.srcFactor = wgpu::BlendFactor::Src,
|
||||||
|
.dstFactor = wgpu::BlendFactor::Zero,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case GX::LO_NOOP:
|
||||||
|
colorBlendComponent = {
|
||||||
|
.operation = wgpu::BlendOperation::Add,
|
||||||
|
.srcFactor = wgpu::BlendFactor::Zero,
|
||||||
|
.dstFactor = wgpu::BlendFactor::Dst,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case GX::LO_INV:
|
||||||
|
colorBlendComponent = {
|
||||||
|
.operation = wgpu::BlendOperation::Add,
|
||||||
|
.srcFactor = wgpu::BlendFactor::Zero,
|
||||||
|
.dstFactor = wgpu::BlendFactor::OneMinusDst,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case GX::LO_INVCOPY:
|
||||||
|
colorBlendComponent = {
|
||||||
|
.operation = wgpu::BlendOperation::Add,
|
||||||
|
.srcFactor = wgpu::BlendFactor::OneMinusSrc,
|
||||||
|
.dstFactor = wgpu::BlendFactor::Zero,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case GX::LO_SET:
|
||||||
|
colorBlendComponent = {
|
||||||
|
.operation = wgpu::BlendOperation::Add,
|
||||||
|
.srcFactor = wgpu::BlendFactor::One,
|
||||||
|
.dstFactor = wgpu::BlendFactor::Zero,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.report(logvisor::Fatal, FMT_STRING("unsupported logic op {}"), op);
|
||||||
|
unreachable();
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("How to {}?"), mode);
|
Log.report(logvisor::Fatal, FMT_STRING("unsupported blend mode {}"), mode);
|
||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
wgpu::BlendComponent alphaBlendComponent{
|
wgpu::BlendComponent alphaBlendComponent{
|
||||||
.operation = wgpu::BlendOperation::Add,
|
.operation = wgpu::BlendOperation::Add,
|
||||||
.srcFactor = wgpu::BlendFactor::Zero,
|
.srcFactor = wgpu::BlendFactor::SrcAlpha,
|
||||||
.dstFactor = wgpu::BlendFactor::One,
|
.dstFactor = wgpu::BlendFactor::Zero,
|
||||||
};
|
};
|
||||||
if (dstAlpha) {
|
if (dstAlpha) {
|
||||||
alphaBlendComponent = wgpu::BlendComponent{
|
alphaBlendComponent = wgpu::BlendComponent{
|
||||||
.operation = wgpu::BlendOperation::Add,
|
.operation = wgpu::BlendOperation::Add,
|
||||||
.srcFactor = wgpu::BlendFactor::Zero,
|
.srcFactor = wgpu::BlendFactor::Constant,
|
||||||
.dstFactor = wgpu::BlendFactor::Constant,
|
.dstFactor = wgpu::BlendFactor::Zero,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
@ -372,7 +428,8 @@ wgpu::RenderPipeline build_pipeline(const PipelineConfig& config, const ShaderIn
|
||||||
.depthWriteEnabled = config.depthUpdate,
|
.depthWriteEnabled = config.depthUpdate,
|
||||||
.depthCompare = to_compare_function(config.depthFunc),
|
.depthCompare = to_compare_function(config.depthFunc),
|
||||||
};
|
};
|
||||||
const auto blendState = to_blend_state(config.blendMode, config.blendFacSrc, config.blendFacDst, config.dstAlpha);
|
const auto blendState =
|
||||||
|
to_blend_state(config.blendMode, config.blendFacSrc, config.blendFacDst, config.blendOp, config.dstAlpha);
|
||||||
const std::array colorTargets{wgpu::ColorTargetState{
|
const std::array colorTargets{wgpu::ColorTargetState{
|
||||||
.format = g_graphicsConfig.colorFormat,
|
.format = g_graphicsConfig.colorFormat,
|
||||||
.blend = &blendState,
|
.blend = &blendState,
|
||||||
|
|
|
@ -67,8 +67,8 @@ struct ColorChannelConfig {
|
||||||
};
|
};
|
||||||
// For uniform generation
|
// For uniform generation
|
||||||
struct ColorChannelState {
|
struct ColorChannelState {
|
||||||
zeus::CColor matColor = zeus::skClear;
|
zeus::CColor matColor;
|
||||||
zeus::CColor ambColor = zeus::skClear;
|
zeus::CColor ambColor;
|
||||||
GX::LightMask lightState;
|
GX::LightMask lightState;
|
||||||
};
|
};
|
||||||
using LightVariant = std::variant<std::monostate, Light, zeus::CColor>;
|
using LightVariant = std::variant<std::monostate, Light, zeus::CColor>;
|
||||||
|
@ -98,7 +98,6 @@ struct TevSwap {
|
||||||
bool operator==(const TevSwap&) const = default;
|
bool operator==(const TevSwap&) const = default;
|
||||||
operator bool() const { return *this != TevSwap{}; }
|
operator bool() const { return *this != TevSwap{}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AlphaCompare {
|
struct AlphaCompare {
|
||||||
GX::Compare comp0 = GX::ALWAYS;
|
GX::Compare comp0 = GX::ALWAYS;
|
||||||
float ref0 = 0.f;
|
float ref0 = 0.f;
|
||||||
|
@ -108,6 +107,7 @@ struct AlphaCompare {
|
||||||
bool operator==(const AlphaCompare& other) const = default;
|
bool operator==(const AlphaCompare& other) const = default;
|
||||||
operator bool() const { return *this != AlphaCompare{}; }
|
operator bool() const { return *this != AlphaCompare{}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GXState {
|
struct GXState {
|
||||||
zeus::CMatrix4f mv;
|
zeus::CMatrix4f mv;
|
||||||
zeus::CMatrix4f mvInv;
|
zeus::CMatrix4f mvInv;
|
||||||
|
@ -274,6 +274,14 @@ inline void xxh3_update(XXH3_state_t& state, const gfx::gx::TcgConfig& input) {
|
||||||
XXH3_64bits_update(&state, &input.normalize, sizeof(gfx::gx::TcgConfig::normalize));
|
XXH3_64bits_update(&state, &input.normalize, sizeof(gfx::gx::TcgConfig::normalize));
|
||||||
}
|
}
|
||||||
template <>
|
template <>
|
||||||
|
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::AlphaCompare& input) {
|
||||||
|
XXH3_64bits_update(&state, &input.comp0, sizeof(gfx::gx::AlphaCompare::comp0));
|
||||||
|
XXH3_64bits_update(&state, &input.ref0, sizeof(gfx::gx::AlphaCompare::ref0));
|
||||||
|
XXH3_64bits_update(&state, &input.op, sizeof(gfx::gx::AlphaCompare::op));
|
||||||
|
XXH3_64bits_update(&state, &input.comp1, sizeof(gfx::gx::AlphaCompare::comp1));
|
||||||
|
XXH3_64bits_update(&state, &input.ref1, sizeof(gfx::gx::AlphaCompare::ref1));
|
||||||
|
}
|
||||||
|
template <>
|
||||||
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ShaderConfig& input) {
|
inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ShaderConfig& input) {
|
||||||
XXH3_64bits_update(&state, &input.fogType, sizeof(gfx::gx::ShaderConfig::fogType));
|
XXH3_64bits_update(&state, &input.fogType, sizeof(gfx::gx::ShaderConfig::fogType));
|
||||||
XXH3_64bits_update(&state, &input.vtxAttrs, sizeof(gfx::gx::ShaderConfig::vtxAttrs));
|
XXH3_64bits_update(&state, &input.vtxAttrs, sizeof(gfx::gx::ShaderConfig::vtxAttrs));
|
||||||
|
@ -291,7 +299,7 @@ inline void xxh3_update(XXH3_state_t& state, const gfx::gx::ShaderConfig& input)
|
||||||
xxh3_update(state, item);
|
xxh3_update(state, item);
|
||||||
}
|
}
|
||||||
if (input.alphaCompare) {
|
if (input.alphaCompare) {
|
||||||
XXH3_64bits_update(&state, &input.alphaCompare, sizeof(gfx::gx::AlphaCompare));
|
xxh3_update(state, input.alphaCompare);
|
||||||
}
|
}
|
||||||
XXH3_64bits_update(&state, &input.hasIndexedAttributes, sizeof(gfx::gx::ShaderConfig::hasIndexedAttributes));
|
XXH3_64bits_update(&state, &input.hasIndexedAttributes, sizeof(gfx::gx::ShaderConfig::hasIndexedAttributes));
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,6 +179,7 @@ void queue_surface(const u8* dlStart, u32 dlSize) noexcept {
|
||||||
.uniformRange = build_uniform(info),
|
.uniformRange = build_uniform(info),
|
||||||
.indexCount = numIndices,
|
.indexCount = numIndices,
|
||||||
.bindGroups = info.bindGroups,
|
.bindGroups = info.bindGroups,
|
||||||
|
.dstAlpha = gx::g_gxState.dstAlpha,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,6 +214,10 @@ void render(const State& state, const DrawData& data, const wgpu::RenderPassEnco
|
||||||
}
|
}
|
||||||
pass.SetVertexBuffer(0, g_vertexBuffer, data.vertRange.offset, data.vertRange.size);
|
pass.SetVertexBuffer(0, g_vertexBuffer, data.vertRange.offset, data.vertRange.size);
|
||||||
pass.SetIndexBuffer(g_indexBuffer, wgpu::IndexFormat::Uint32, data.idxRange.offset, data.idxRange.size);
|
pass.SetIndexBuffer(g_indexBuffer, wgpu::IndexFormat::Uint32, data.idxRange.offset, data.idxRange.size);
|
||||||
|
if (data.dstAlpha) {
|
||||||
|
const wgpu::Color color{0.f, 0.f, 0.f, *data.dstAlpha};
|
||||||
|
pass.SetBlendConstant(&color);
|
||||||
|
}
|
||||||
pass.DrawIndexed(data.indexCount);
|
pass.DrawIndexed(data.indexCount);
|
||||||
}
|
}
|
||||||
} // namespace aurora::gfx::model
|
} // namespace aurora::gfx::model
|
||||||
|
|
|
@ -12,6 +12,7 @@ struct DrawData {
|
||||||
Range uniformRange;
|
Range uniformRange;
|
||||||
uint32_t indexCount;
|
uint32_t indexCount;
|
||||||
gx::GXBindGroups bindGroups;
|
gx::GXBindGroups bindGroups;
|
||||||
|
std::optional<float> dstAlpha;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PipelineConfig : gx::PipelineConfig {};
|
struct PipelineConfig : gx::PipelineConfig {};
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct SStreamState {
|
||||||
aurora::ByteBuffer vertexBuffer;
|
aurora::ByteBuffer vertexBuffer;
|
||||||
std::vector<u16> indices;
|
std::vector<u16> indices;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
GX::Attr currentAttr{};
|
GX::Attr nextAttr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
explicit SStreamState(GX::Primitive primitive, u16 numVerts, u16 vertexSize) noexcept : primitive(primitive) {
|
explicit SStreamState(GX::Primitive primitive, u16 numVerts, u16 vertexSize) noexcept : primitive(primitive) {
|
||||||
|
@ -26,6 +26,10 @@ struct SStreamState {
|
||||||
} else {
|
} else {
|
||||||
indices.reserve(numVerts);
|
indices.reserve(numVerts);
|
||||||
}
|
}
|
||||||
|
#ifndef NDEBUG
|
||||||
|
nextAttr =
|
||||||
|
GX::Attr(std::find(g_gxState.vtxDesc.begin(), g_gxState.vtxDesc.end(), GX::DIRECT) - g_gxState.vtxDesc.begin());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static std::optional<SStreamState> sStreamState;
|
static std::optional<SStreamState> sStreamState;
|
||||||
|
@ -68,29 +72,26 @@ static inline void check_attr_order(GX::Attr attr) noexcept {
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("Stream not started!"));
|
Log.report(logvisor::Fatal, FMT_STRING("Stream not started!"));
|
||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
if (sStreamState->currentAttr >= attr) {
|
if (sStreamState->nextAttr != attr) {
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("bad attribute order: {}, last {}"), attr, sStreamState->currentAttr);
|
Log.report(logvisor::Fatal, FMT_STRING("bad attribute order: {}, expected {}"), attr, sStreamState->nextAttr);
|
||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
sStreamState->currentAttr = attr;
|
auto nextAttr = std::find(g_gxState.vtxDesc.begin() + attr + 1, g_gxState.vtxDesc.end(), GX::DIRECT);
|
||||||
|
if (nextAttr == g_gxState.vtxDesc.end()) {
|
||||||
|
nextAttr = std::find(g_gxState.vtxDesc.begin(), g_gxState.vtxDesc.end(), GX::DIRECT);
|
||||||
|
}
|
||||||
|
sStreamState->nextAttr = GX::Attr(nextAttr - g_gxState.vtxDesc.begin());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
void GXPosition3f32(const zeus::CVector3f& pos) noexcept {
|
void GXPosition3f32(const zeus::CVector3f& pos) noexcept {
|
||||||
#ifndef NDEBUG
|
check_attr_order(GX::VA_POS);
|
||||||
if (!sStreamState) {
|
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("Stream not started!"));
|
|
||||||
unreachable();
|
|
||||||
}
|
|
||||||
sStreamState->currentAttr = GX::VA_POS;
|
|
||||||
#endif
|
|
||||||
auto& state = *sStreamState;
|
auto& state = *sStreamState;
|
||||||
state.vertexBuffer.append(&pos, 12);
|
state.vertexBuffer.append(&pos, 12);
|
||||||
if (state.primitive == GX::TRIANGLES || state.vertexCount < 3) {
|
if (state.primitive == GX::TRIANGLES || state.vertexCount < 3) {
|
||||||
state.indices.push_back(state.vertexCount);
|
// pass
|
||||||
} else if (state.primitive == GX::TRIANGLEFAN) {
|
} else if (state.primitive == GX::TRIANGLEFAN) {
|
||||||
state.indices.push_back(0);
|
state.indices.push_back(0);
|
||||||
state.indices.push_back(state.vertexCount - 1);
|
state.indices.push_back(state.vertexCount - 1);
|
||||||
state.indices.push_back(state.vertexCount);
|
|
||||||
} else if (state.primitive == GX::TRIANGLESTRIP) {
|
} else if (state.primitive == GX::TRIANGLESTRIP) {
|
||||||
if ((state.vertexCount & 1) == 0) {
|
if ((state.vertexCount & 1) == 0) {
|
||||||
state.indices.push_back(state.vertexCount - 2);
|
state.indices.push_back(state.vertexCount - 2);
|
||||||
|
@ -99,16 +100,13 @@ void GXPosition3f32(const zeus::CVector3f& pos) noexcept {
|
||||||
state.indices.push_back(state.vertexCount - 1);
|
state.indices.push_back(state.vertexCount - 1);
|
||||||
state.indices.push_back(state.vertexCount - 2);
|
state.indices.push_back(state.vertexCount - 2);
|
||||||
}
|
}
|
||||||
state.indices.push_back(state.vertexCount);
|
|
||||||
} else if (state.primitive == GX::QUADS) {
|
} else if (state.primitive == GX::QUADS) {
|
||||||
if ((state.vertexCount & 3) == 3) {
|
if ((state.vertexCount & 3) == 3) {
|
||||||
state.indices.push_back(state.vertexCount - 1);
|
|
||||||
state.indices.push_back(state.vertexCount);
|
|
||||||
state.indices.push_back(state.vertexCount - 3);
|
state.indices.push_back(state.vertexCount - 3);
|
||||||
} else {
|
state.indices.push_back(state.vertexCount - 1);
|
||||||
state.indices.push_back(state.vertexCount);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
state.indices.push_back(state.vertexCount);
|
||||||
++state.vertexCount;
|
++state.vertexCount;
|
||||||
}
|
}
|
||||||
void GXNormal3f32(const zeus::CVector3f& nrm) noexcept {
|
void GXNormal3f32(const zeus::CVector3f& nrm) noexcept {
|
||||||
|
@ -124,6 +122,10 @@ void GXTexCoord2f32(const zeus::CVector2f& uv) noexcept {
|
||||||
sStreamState->vertexBuffer.append(&uv, 8);
|
sStreamState->vertexBuffer.append(&uv, 8);
|
||||||
}
|
}
|
||||||
void GXEnd() noexcept {
|
void GXEnd() noexcept {
|
||||||
|
if (sStreamState->vertexCount == 0) {
|
||||||
|
sStreamState.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto vertRange = aurora::gfx::push_verts(sStreamState->vertexBuffer.data(), sStreamState->vertexBuffer.size());
|
const auto vertRange = aurora::gfx::push_verts(sStreamState->vertexBuffer.data(), sStreamState->vertexBuffer.size());
|
||||||
const auto indexRange = aurora::gfx::push_indices(aurora::ArrayRef{sStreamState->indices});
|
const auto indexRange = aurora::gfx::push_indices(aurora::ArrayRef{sStreamState->indices});
|
||||||
aurora::gfx::stream::PipelineConfig config{};
|
aurora::gfx::stream::PipelineConfig config{};
|
||||||
|
@ -136,6 +138,7 @@ void GXEnd() noexcept {
|
||||||
.indexRange = indexRange,
|
.indexRange = indexRange,
|
||||||
.indexCount = static_cast<uint32_t>(sStreamState->indices.size()),
|
.indexCount = static_cast<uint32_t>(sStreamState->indices.size()),
|
||||||
.bindGroups = info.bindGroups,
|
.bindGroups = info.bindGroups,
|
||||||
|
.dstAlpha = g_gxState.dstAlpha,
|
||||||
});
|
});
|
||||||
sStreamState.reset();
|
sStreamState.reset();
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,10 @@ void render(const State& state, const DrawData& data, const wgpu::RenderPassEnco
|
||||||
}
|
}
|
||||||
pass.SetVertexBuffer(0, g_vertexBuffer, data.vertRange.offset, data.vertRange.size);
|
pass.SetVertexBuffer(0, g_vertexBuffer, data.vertRange.offset, data.vertRange.size);
|
||||||
pass.SetIndexBuffer(g_indexBuffer, wgpu::IndexFormat::Uint16, data.indexRange.offset, data.indexRange.size);
|
pass.SetIndexBuffer(g_indexBuffer, wgpu::IndexFormat::Uint16, data.indexRange.offset, data.indexRange.size);
|
||||||
|
if (data.dstAlpha) {
|
||||||
|
const wgpu::Color color{0.f, 0.f, 0.f, *data.dstAlpha};
|
||||||
|
pass.SetBlendConstant(&color);
|
||||||
|
}
|
||||||
pass.DrawIndexed(data.indexCount);
|
pass.DrawIndexed(data.indexCount);
|
||||||
}
|
}
|
||||||
} // namespace aurora::gfx::stream
|
} // namespace aurora::gfx::stream
|
||||||
|
|
|
@ -11,6 +11,7 @@ struct DrawData {
|
||||||
Range indexRange;
|
Range indexRange;
|
||||||
uint32_t indexCount;
|
uint32_t indexCount;
|
||||||
gx::GXBindGroups bindGroups;
|
gx::GXBindGroups bindGroups;
|
||||||
|
std::optional<float> dstAlpha;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PipelineConfig : public gx::PipelineConfig {};
|
struct PipelineConfig : public gx::PipelineConfig {};
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 11606d3676f4bd60e70e1bbd045f55352257dbb6
|
Subproject commit f3e649716af215157b1d64a0f25de8e1d7f185fa
|
Loading…
Reference in New Issue