mirror of
https://github.com/zeldaret/ss
synced 2026-05-24 15:20:58 -04:00
247 lines
9.1 KiB
C++
247 lines
9.1 KiB
C++
#include "egg/gfx/eggPostEffectMaskDOF.h"
|
|
|
|
#include "common.h"
|
|
#include "egg/gfx/eggCpuTexture.h"
|
|
#include "nw4r/math/math_types.h"
|
|
#include "rvl/GX/GXGeometry.h"
|
|
#include "rvl/GX/GXTransform.h"
|
|
#include "rvl/GX/GXTypes.h"
|
|
#include "rvl/MTX/mtx.h"
|
|
|
|
namespace EGG {
|
|
|
|
static const GXColor sColorNear = (GXColor){0x00, 0xFF, 0x00, 0xFF};
|
|
static const GXColor sColorFar = (GXColor){0xFF, 0x00, 0x00, 0x00};
|
|
static const GXColor sColorCenter = (GXColor){0x00, 0x00, 0x00, 0x00};
|
|
|
|
PostEffectMaskDOF::PostEffectMaskDOF()
|
|
: field_0x2C(8),
|
|
field_0x44(0.5),
|
|
field_0x48(0.f),
|
|
field_0x4C(1.f),
|
|
field_0x50(0.f, 0.f),
|
|
mCpuTexArrIdx(2),
|
|
field_0x60(2) {
|
|
for (int i = 0; i < 3; i++) {
|
|
mpCpuTexArr[i] = new CpuTexture(64, 2, GX_TF_RGBA8);
|
|
mpCpuTexArr[i]->configure();
|
|
mpCpuTexArr[i]->allocate(nullptr);
|
|
mpCpuTexArr[i]->setWrapS(GX_CLAMP);
|
|
mpCpuTexArr[i]->setWrapT(GX_CLAMP);
|
|
}
|
|
|
|
mpCpuTex = new CpuTexture(64, 64, GX_TF_RGBA8);
|
|
mpCpuTex->configure();
|
|
mpCpuTex->allocate(nullptr);
|
|
mpCpuTex->setWrapS(GX_CLAMP);
|
|
mpCpuTex->setWrapT(GX_CLAMP);
|
|
setUpGradation();
|
|
field_0x00 = 0;
|
|
}
|
|
|
|
void PostEffectMaskDOF::setUpGradation() {
|
|
for (int i = 0; i < 3; i++) {
|
|
const u16 width = mpCpuTexArr[i]->getWidth();
|
|
const int mid = width / 2;
|
|
for (u16 x = 0; x < mid; x++) {
|
|
f32 val = 1.f - (f32)x / (mid - 1);
|
|
|
|
switch (i) {
|
|
case 1: val *= val; break;
|
|
case 2:
|
|
val *= val;
|
|
val *= val;
|
|
break;
|
|
}
|
|
|
|
GXColor clr1, clr2;
|
|
lerpColor(clr1, getCenterColor(), getNearColor(), val);
|
|
lerpColor(clr2, getCenterColor(), getFarColor(), val);
|
|
|
|
mpCpuTexArr[i]->setColor(x, 0, clr1);
|
|
mpCpuTexArr[i]->setColor(x, 1, clr1);
|
|
mpCpuTexArr[i]->setColor((width - 1) - x, 0, clr2);
|
|
mpCpuTexArr[i]->setColor((width - 1) - x, 1, clr2);
|
|
}
|
|
mpCpuTexArr[i]->flush();
|
|
}
|
|
|
|
const u16 width = mpCpuTex->getWidth() / 2;
|
|
for (u16 y = 0; y < mpCpuTex->getHeight(); y++) {
|
|
f32 fy = (f32)y / mpCpuTex->getHeight2();
|
|
for (u16 x = 0; x < width; x++) {
|
|
// Don't even have to use this one!
|
|
(void)(f32)width;
|
|
f32 ratio = ((f32)x / width) / (1.f - fy);
|
|
|
|
if (ratio > 1.f) {
|
|
ratio = 1.f;
|
|
} else if (ratio < 0.f) {
|
|
ratio = 0.f;
|
|
}
|
|
ratio *= ratio;
|
|
ratio *= ratio;
|
|
GXColor clr1, clr2;
|
|
lerpColor(clr1, getCenterColor(), getNearColor(), ratio);
|
|
lerpColor(clr2, getCenterColor(), getFarColor(), ratio);
|
|
mpCpuTex->setColor((width - 1) - x, y, clr1);
|
|
mpCpuTex->setColor(width + x, y, clr2);
|
|
}
|
|
}
|
|
mpCpuTex->flush();
|
|
}
|
|
|
|
void PostEffectMaskDOF::draw(f32 width, f32 height) {
|
|
setMaterialInternal();
|
|
setVtxState();
|
|
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX1, GX_TEX_ST, GX_F32, 0);
|
|
GXSetVtxDesc(GX_VA_TEX1, GX_DIRECT);
|
|
nw4r::math::MTX34 mtx;
|
|
PSMTXScale(mtx, width * mScaleX, height * mScaleY, 1.f);
|
|
PSMTXTransApply(mtx, mtx, mOffsetX, mOffsetY, 0.f);
|
|
GXLoadPosMtxImm(mtx, GX_PNMTX0);
|
|
GXBegin(GX_QUADS, GX_VTXFMT0, 4);
|
|
GXPosition2u8(0, 0);
|
|
GXPosition2f32(field_0x50.x, field_0x50.y);
|
|
GXPosition2u8(1, 1);
|
|
GXPosition2f32(field_0x50.x, field_0x50.y);
|
|
GXPosition2u8(2, 2);
|
|
GXPosition2f32(field_0x50.x, field_0x50.y);
|
|
GXPosition2u8(3, 3);
|
|
GXPosition2f32(field_0x50.x, field_0x50.y);
|
|
GXSetTexCoordScaleManually(GX_TEXCOORD1, 0, 0x40, 0);
|
|
GXSetTexCoordBias(GX_TEXCOORD1, 0, 0);
|
|
}
|
|
|
|
void PostEffectMaskDOF::setMaterialInternal() {
|
|
loadTextureInternal();
|
|
setMatColorChannel();
|
|
GXSetNumTexGens(2);
|
|
GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0, false, GX_DUALMTX_IDENT);
|
|
GXSetTexCoordGen2(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY, false, GX_DUALMTX_IDENT);
|
|
nw4r::math::MTX34 baseTexMtx;
|
|
getBaseTexMtx(&baseTexMtx);
|
|
GXLoadTexMtxImm(baseTexMtx, GX_TEXMTX0, GX_MTX2x4);
|
|
GXSetNumIndStages(1);
|
|
GXSetIndTexOrder(GX_INDTEXSTAGE0, GX_TEXCOORD0, mTex1.mTexMapID);
|
|
GXSetIndTexCoordScale(GX_INDTEXSTAGE0, GX_ITS_1, GX_ITS_1);
|
|
|
|
CpuTexture *pCpuTex = mpCpuTexArr[mCpuTexArrIdx];
|
|
switch (field_0x60) {
|
|
case 0: {
|
|
GXSetNumTevStages(1);
|
|
GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
|
|
GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0);
|
|
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD1, GX_TEXMAP2, GX_COLOR_NULL);
|
|
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC);
|
|
GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
|
|
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA);
|
|
GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV);
|
|
GXSetTevIndirect(
|
|
GX_TEVSTAGE0, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_0, GX_ITW_OFF, GX_ITW_OFF, false, false,
|
|
GX_ITBA_OFF
|
|
);
|
|
|
|
s8 scaleExp = 0;
|
|
f32 fVar2 = scaleExp + 1;
|
|
f32 fVar3 = 1.f / (field_0x4C - field_0x48);
|
|
|
|
f32 fVar1 = fVar3 / fVar2;
|
|
|
|
while (fVar1 > (1023.f / 1024.f)) {
|
|
fVar1 /= 2.f;
|
|
fVar2 *= 2.f;
|
|
|
|
scaleExp++;
|
|
}
|
|
while (0.f < fVar1 && fVar1 < 0.5f) {
|
|
fVar1 *= 2.f;
|
|
fVar2 /= 2.f;
|
|
|
|
scaleExp--;
|
|
}
|
|
f32 indTexMtx[2][3] = {
|
|
{fVar1 / 256.f, fVar1, 0.f},
|
|
{ 0.f, 0.f, 0.f}
|
|
};
|
|
GXSetIndTexMtx(GX_ITM_0, indTexMtx, scaleExp - 2);
|
|
field_0x50.x = -(field_0x44 * fVar1 * fVar2) + 0.5f;
|
|
if (field_0x2C & 8) {
|
|
field_0x50.x = (s32)(field_0x50.x * 128.f) / 128.f;
|
|
}
|
|
field_0x50.y = 0.f;
|
|
GXSetTexCoordScaleManually(GX_TEXCOORD1, true, 0x40, 0);
|
|
GXSetTexCoordBias(GX_TEXCOORD1, 0, 0);
|
|
} break;
|
|
case 1: {
|
|
pCpuTex = mpCpuTex;
|
|
GXSetNumTevStages(2);
|
|
GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
|
|
GXSetTevDirect(GX_TEVSTAGE0);
|
|
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD1, GX_TEXMAP2, GX_COLOR_NULL);
|
|
GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0);
|
|
GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP2, GX_COLOR_NULL);
|
|
GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC);
|
|
GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
|
|
GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA);
|
|
GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV);
|
|
GXSetTevIndirect(
|
|
GX_TEVSTAGE1, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_0, GX_ITW_0, GX_ITW_0, true, false,
|
|
GX_ITBA_OFF
|
|
);
|
|
field_0x50.y = field_0x4C;
|
|
|
|
f32 val = 1023.f / 1024.f;
|
|
f32 indTexMtx[2][3] = {
|
|
{val / 256.f, val, 0.f},
|
|
{ 0.f, 0.f, 0.f}
|
|
};
|
|
|
|
GXSetIndTexMtx(GX_ITM_0, indTexMtx, 8);
|
|
|
|
int unk = 1024;
|
|
field_0x50.x = -field_0x44 + 0.5f / unk;
|
|
|
|
GXSetTexCoordScaleManually(GX_TEXCOORD1, GX_TEXCOORD1, 0, 0x40);
|
|
GXSetTexCoordBias(GX_TEXCOORD1, 0, 0);
|
|
} break;
|
|
case 2: {
|
|
GXSetNumTevStages(1);
|
|
GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
|
|
GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0);
|
|
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP2, GX_COLOR_NULL);
|
|
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC);
|
|
GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
|
|
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA);
|
|
GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV);
|
|
GXSetTevIndirect(
|
|
GX_TEVSTAGE0, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_0, GX_ITW_0, GX_ITW_0, false, false,
|
|
GX_ITBA_OFF
|
|
);
|
|
|
|
f32 indTexMtx[2][3] = {
|
|
{0.f, 0.5f, 0.f},
|
|
{0.f, 0.f, 0.f}
|
|
};
|
|
GXSetIndTexMtx(GX_ITM_0, indTexMtx, -1);
|
|
|
|
field_0x50.y = 0.f;
|
|
field_0x50.x = 0.f;
|
|
} break;
|
|
}
|
|
pCpuTex->load(GX_TEXMAP2);
|
|
setMatPE();
|
|
}
|
|
|
|
const GXColor &PostEffectMaskDOF::getNearColor() {
|
|
return sColorNear;
|
|
}
|
|
const GXColor &PostEffectMaskDOF::getFarColor() {
|
|
return sColorFar;
|
|
}
|
|
const GXColor &PostEffectMaskDOF::getCenterColor() {
|
|
return sColorCenter;
|
|
}
|
|
|
|
} // namespace EGG
|