mirror of https://github.com/AxioDL/metaforce.git
CDecal: Fixes from decomp & implement RenderQuad
This commit is contained in:
parent
5cd27373f4
commit
132ee9e332
|
@ -3,6 +3,7 @@
|
|||
#include "Runtime/Graphics/CModel.hpp"
|
||||
#include "Runtime/Graphics/Shaders/CDecalShaders.hpp"
|
||||
#include "Runtime/Particle/CParticleGlobals.hpp"
|
||||
#include "Runtime/Graphics/CGX.hpp"
|
||||
|
||||
namespace metaforce {
|
||||
CRandom16 CDecal::sDecalRandom;
|
||||
|
@ -41,18 +42,20 @@ bool CDecal::InitQuad(CQuadDecal& quad, const SQuadDescr& desc) {
|
|||
}
|
||||
if (desc.x8_ROT) {
|
||||
desc.x8_ROT->GetValue(0, quad.x8_rotation);
|
||||
quad.x0_24_invalid = desc.x8_ROT->IsConstant();
|
||||
quad.x0_24_invalid &= desc.x8_ROT->IsConstant();
|
||||
}
|
||||
|
||||
if (desc.x4_SZE) {
|
||||
quad.x0_24_invalid = desc.x4_SZE->IsConstant();
|
||||
float size = 1.f;
|
||||
desc.x4_SZE->GetValue(0, size);
|
||||
quad.x0_24_invalid = size <= 1.f;
|
||||
quad.x0_24_invalid &= desc.x4_SZE->IsConstant();
|
||||
if (quad.x0_24_invalid) {
|
||||
float size = 1.f;
|
||||
desc.x4_SZE->GetValue(0, size);
|
||||
quad.x0_24_invalid = size <= 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
if (desc.xc_OFF) {
|
||||
quad.x0_24_invalid = desc.xc_OFF->IsFastConstant();
|
||||
quad.x0_24_invalid &= desc.xc_OFF->IsFastConstant();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -86,73 +89,104 @@ void CDecal::RenderQuad(CQuadDecal& decal, const SQuadDescr& desc) const {
|
|||
zeus::CTransform modXf = xc_transform;
|
||||
modXf.origin += offset;
|
||||
CGraphics::SetModelMatrix(modXf);
|
||||
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
|
||||
|
||||
// SParticleUniforms uniformData = {
|
||||
// CGraphics::GetPerspectiveProjectionMatrix(/*true*/) * CGraphics::g_GXModelView.toMatrix4f(), {1.f, 1.f, 1.f, 1.f}};
|
||||
// decal.m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms));
|
||||
|
||||
bool redToAlpha = sMoveRedToAlphaBuffer && desc.x18_ADD && desc.x14_TEX;
|
||||
|
||||
SUVElementSet uvSet = {0.f, 1.f, 0.f, 1.f};
|
||||
if (CUVElement* tex = desc.x14_TEX.get()) {
|
||||
TLockedToken<CTexture> texObj = tex->GetValueTexture(x58_frameIdx);
|
||||
if (!texObj.IsLoaded())
|
||||
return;
|
||||
tex->GetValueUV(x58_frameIdx, uvSet);
|
||||
// if (redToAlpha)
|
||||
// CGraphics::SetShaderDataBinding(decal.m_redToAlphaDataBind);
|
||||
// else
|
||||
// CGraphics::SetShaderDataBinding(decal.m_normalDataBind);
|
||||
|
||||
// g_instTexData.clear();
|
||||
// g_instTexData.reserve(1);
|
||||
|
||||
// SParticleInstanceTex& inst = g_instTexData.emplace_back();
|
||||
// if (decal.x8_rotation == 0.f) {
|
||||
// inst.pos[0] = zeus::CVector3f(-size, 0.001f, size);
|
||||
// inst.pos[1] = zeus::CVector3f(size, 0.001f, size);
|
||||
// inst.pos[2] = zeus::CVector3f(-size, 0.001f, -size);
|
||||
// inst.pos[3] = zeus::CVector3f(size, 0.001f, -size);
|
||||
// } else {
|
||||
// float ang = zeus::degToRad(decal.x8_rotation);
|
||||
// float sinSize = std::sin(ang) * size;
|
||||
// float cosSize = std::cos(ang) * size;
|
||||
// inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 0.001f, cosSize + sinSize);
|
||||
// inst.pos[1] = zeus::CVector3f(cosSize + sinSize, 0.001f, cosSize - sinSize);
|
||||
// inst.pos[2] = zeus::CVector3f(-(cosSize + sinSize), 0.001f, -(cosSize - sinSize));
|
||||
// inst.pos[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize);
|
||||
// }
|
||||
// inst.color = color;
|
||||
// inst.uvs[0] = zeus::CVector2f(uvSet.xMin, uvSet.yMin);
|
||||
// inst.uvs[1] = zeus::CVector2f(uvSet.xMax, uvSet.yMin);
|
||||
// inst.uvs[2] = zeus::CVector2f(uvSet.xMin, uvSet.yMax);
|
||||
// inst.uvs[3] = zeus::CVector2f(uvSet.xMax, uvSet.yMax);
|
||||
|
||||
// decal.m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
|
||||
// CGraphics::DrawInstances(0, 4, g_instTexData.size());
|
||||
bool redToAlpha = CDecal::sMoveRedToAlphaBuffer && desc.x18_ADD && desc.x14_TEX;
|
||||
if (desc.x18_ADD) {
|
||||
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, false);
|
||||
if (redToAlpha) {
|
||||
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear);
|
||||
} else {
|
||||
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One,
|
||||
ERglLogicOp::Clear);
|
||||
}
|
||||
} else {
|
||||
// g_instNoTexData.clear();
|
||||
// g_instNoTexData.reserve(1);
|
||||
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, false);
|
||||
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha,
|
||||
ERglLogicOp::Clear);
|
||||
}
|
||||
|
||||
// SParticleInstanceNoTex& inst = g_instNoTexData.emplace_back();
|
||||
// if (decal.x8_rotation == 0.f) {
|
||||
// inst.pos[0] = zeus::CVector3f(-size, 0.001f, size);
|
||||
// inst.pos[1] = zeus::CVector3f(size, 0.001f, size);
|
||||
// inst.pos[2] = zeus::CVector3f(-size, 0.001f, -size);
|
||||
// inst.pos[3] = zeus::CVector3f(size, 0.001f, -size);
|
||||
// } else {
|
||||
// float ang = zeus::degToRad(decal.x8_rotation);
|
||||
// float sinSize = std::sin(ang) * size;
|
||||
// float cosSize = std::cos(ang) * size;
|
||||
// inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 0.001f, cosSize + sinSize);
|
||||
// inst.pos[1] = zeus::CVector3f(cosSize + sinSize, 0.001f, cosSize - sinSize);
|
||||
// inst.pos[2] = zeus::CVector3f(-(cosSize + sinSize), 0.001f, -(cosSize - sinSize));
|
||||
// inst.pos[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize);
|
||||
// }
|
||||
// inst.color = color;
|
||||
SUVElementSet uvSet{0.f, 1.f, 0.f, 1.f};
|
||||
if (desc.x14_TEX) {
|
||||
TLockedToken<CTexture> tex = desc.x14_TEX->GetValueTexture(x58_frameIdx);
|
||||
tex->Load(GX_TEXMAP0, EClampMode::Repeat);
|
||||
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::kEnvModulate);
|
||||
desc.x14_TEX->GetValueUV(x58_frameIdx, uvSet);
|
||||
if (redToAlpha) {
|
||||
CGX::SetNumTevStages(2);
|
||||
CGX::SetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_CPREV, GX_CC_APREV, GX_CC_ZERO);
|
||||
CGX::SetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_TEXA, GX_CA_APREV, GX_CA_ZERO);
|
||||
CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE1);
|
||||
CGX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_NEVER, 0);
|
||||
GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP1);
|
||||
} else {
|
||||
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::kEnvPassthru);
|
||||
}
|
||||
} else {
|
||||
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::kEnvPassthru);
|
||||
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::kEnvPassthru);
|
||||
}
|
||||
|
||||
// decal.m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
|
||||
// CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
|
||||
CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
|
||||
CGX::SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
|
||||
CGX::SetNumTexGens(1);
|
||||
CGX::SetNumChans(1);
|
||||
CGX::SetNumIndStages(0);
|
||||
CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, false, GX_PTIDENTITY);
|
||||
CGX::SetChanCtrl(CGX::EChannelId::Channel0, false, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
|
||||
static const GXVtxDescList vtxDesc[4] = {
|
||||
{GX_VA_POS, GX_DIRECT},
|
||||
{GX_VA_CLR0, GX_DIRECT},
|
||||
{GX_VA_TEX0, GX_DIRECT},
|
||||
{GX_VA_NULL, GX_NONE},
|
||||
};
|
||||
CGX::SetVtxDescv(vtxDesc);
|
||||
CGX::Begin(GX_TRIANGLESTRIP, GX_VTXFMT0, 4);
|
||||
|
||||
float y = 0.001f;
|
||||
if (decal.x8_rotation == 0.f) {
|
||||
// Vertex 0
|
||||
GXPosition3f32(-size, y, size);
|
||||
GXColor4f32(color);
|
||||
GXTexCoord2f32(uvSet.xMin, uvSet.yMin);
|
||||
// Vertex 1
|
||||
GXPosition3f32(size, y, size);
|
||||
GXColor4f32(color);
|
||||
GXTexCoord2f32(uvSet.xMax, uvSet.yMin);
|
||||
// Vertex 2
|
||||
GXPosition3f32(-size, y, -size);
|
||||
GXColor4f32(color);
|
||||
GXTexCoord2f32(uvSet.xMin, uvSet.yMax);
|
||||
// Vertex 3
|
||||
GXPosition3f32(size, y, -size);
|
||||
GXColor4f32(color);
|
||||
GXTexCoord2f32(uvSet.xMax, uvSet.yMax);
|
||||
} else {
|
||||
float ang = zeus::degToRad(decal.x8_rotation);
|
||||
float sinSize = sin(ang) * size;
|
||||
float cosSize = cos(ang) * size;
|
||||
// Vertex 0
|
||||
GXPosition3f32(sinSize - cosSize, y, cosSize + sinSize);
|
||||
GXColor4f32(color);
|
||||
GXTexCoord2f32(uvSet.xMin, uvSet.yMin);
|
||||
// Vertex 1
|
||||
GXPosition3f32(cosSize + sinSize, y, cosSize - sinSize);
|
||||
GXColor4f32(color);
|
||||
GXTexCoord2f32(uvSet.xMax, uvSet.yMin);
|
||||
// Vertex 2
|
||||
GXPosition3f32(-(cosSize + sinSize), y, -(cosSize - sinSize));
|
||||
GXColor4f32(color);
|
||||
GXTexCoord2f32(uvSet.xMin, uvSet.yMax);
|
||||
// Vertex 3
|
||||
GXPosition3f32(-sinSize + cosSize, y, -cosSize - sinSize);
|
||||
GXColor4f32(color);
|
||||
GXTexCoord2f32(uvSet.xMax, uvSet.yMax);
|
||||
}
|
||||
|
||||
CGX::End();
|
||||
if (redToAlpha) {
|
||||
GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0);
|
||||
CGX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue