From d676fd1602f4b0ae32e8669d429467242ce93a0c Mon Sep 17 00:00:00 2001
From: kiwi515 <49212064+kiwi515@users.noreply.github.com>
Date: Sat, 12 Sep 2026 16:21:08 -0400
Subject: [PATCH 1/4] stuff
---
config/RSPE01_01/symbols.txt | 88 ++--
configure.py | 4 +-
include/Pack/RPGraphics.h | 3 +
include/Pack/RPGraphics/RPGrpModelManager.h | 12 +
include/Pack/RPGraphics/RPGrpModelScene.h | 32 ++
include/Pack/RPGraphics/RPGrpRenderer.h | 4 +-
include/Pack/RPGraphics/RPGrpView.h | 359 +++++++++++++++-
include/Pack/RPGraphics/RPGrpViewRender2D.h | 47 +++
include/Pack/RPGraphics/RPGrpViewRender3D.h | 76 ++++
include/Pack/RPKernel/RPSysEffectCreator.h | 5 +-
include/Pack/RPKernel/RPSysEffectMgr.h | 5 +-
include/egg/gfxe.h | 3 +
include/egg/gfxe/eggCapTexture.h | 3 +
include/egg/gfxe/eggFrustum.h | 4 +
include/egg/gfxe/eggPostEffectBlurSimple.h | 21 +
include/egg/gfxe/eggScreen.h | 2 +-
include/egg/gfxe/eggStateGX.h | 10 +-
src/Pack/RPGraphics/RPGrpView.cpp | 435 ++++++++++++++++++++
src/Pack/RPGraphics/RPGrpViewRender2D.cpp | 35 ++
src/Pack/RPGraphics/RPGrpViewRender3D.cpp | 101 +++++
src/Pack/RPKernel/RPSysEffectCreator.cpp | 24 +-
src/Pack/RPKernel/RPSysEffectMgr.cpp | 12 +-
22 files changed, 1200 insertions(+), 85 deletions(-)
create mode 100644 include/Pack/RPGraphics/RPGrpModelScene.h
create mode 100644 include/Pack/RPGraphics/RPGrpViewRender2D.h
create mode 100644 include/Pack/RPGraphics/RPGrpViewRender3D.h
create mode 100644 include/egg/gfxe/eggPostEffectBlurSimple.h
create mode 100644 src/Pack/RPGraphics/RPGrpView.cpp
create mode 100644 src/Pack/RPGraphics/RPGrpViewRender2D.cpp
create mode 100644 src/Pack/RPGraphics/RPGrpViewRender3D.cpp
diff --git a/config/RSPE01_01/symbols.txt b/config/RSPE01_01/symbols.txt
index 019607a39..5fe01cc90 100644
--- a/config/RSPE01_01/symbols.txt
+++ b/config/RSPE01_01/symbols.txt
@@ -7310,7 +7310,7 @@ AllocHeap__24RPSysEffectMemoryManagerFUl = .text:0x80193100; // type:function si
RoundUp
__Q34nw4r2ut24@unnamed@SportsPack_pch@FUlUi_Ul = .text:0x80193250; // type:function size:0x18 scope:weak
__ct__Q34nw4r2ef17MemoryManagerBaseFv = .text:0x80193268; // type:function size:0x10 scope:weak
createEffect__14RPSysEffectMgrFPCcUlUl = .text:0x80193278; // type:function size:0x10
-draw__14RPSysEffectMgrFRCQ34nw4r2ef8DrawInfoUlUl = .text:0x80193288; // type:function size:0x22C
+draw__14RPSysEffectMgrFRCQ34nw4r4math5MTX34UlUl = .text:0x80193288; // type:function size:0x22C
setCaptureEfb__14RPSysEffectMgrFPvRCQ214RPSysEffectMgr10EfbTexData = .text:0x801934B4; // type:function size:0xD0
update__14RPSysEffectMgrFQ214RPSysEffectMgr12ECalcSetting = .text:0x80193584; // type:function size:0x7C
stopAllEffect__14RPSysEffectMgrFv = .text:0x80193600; // type:function size:0x9C
@@ -7942,7 +7942,7 @@ __ct__20RPGrpModelResManagerFv = .text:0x801AF184; // type:function size:0x10
__dt__20RPGrpModelResManagerFv = .text:0x801AF194; // type:function size:0x40
fn_801AF1D4 = .text:0x801AF1D4; // type:function size:0x4
fn_801AF1D8 = .text:0x801AF1D8; // type:function size:0x230
-fn_801AF408 = .text:0x801AF408; // type:function size:0x4
+PrepareDrawGX__9RPGrpViewFv = .text:0x801AF408; // type:function size:0x4
fn_801AF40C = .text:0x801AF40C; // type:function size:0x24
AppendDrawObject__13RPGrpRendererFP16IRPGrpDrawObject = .text:0x801AF430; // type:function size:0x24
fn_801AF454 = .text:0x801AF454; // type:function size:0x138
@@ -7971,42 +7971,42 @@ DrawQuad__11RPGrpScreenCFffff8_GXColor = .text:0x801B0378; // type:function size
BeginDrawQuad__11RPGrpScreenCFv = .text:0x801B03E8; // type:function size:0x1C
Initialize__11RPGrpScreenFPCUsPCUs = .text:0x801B0404; // type:function size:0xC
__sinit_\RPGrpScreen_cpp = .text:0x801B0410; // type:function size:0x5C scope:local
-fn_801B046C = .text:0x801B046C; // type:function size:0x734
-fn_801B0BA0 = .text:0x801B0BA0; // type:function size:0x150
-fn_801B0CF0 = .text:0x801B0CF0; // type:function size:0x184
-fn_801B0E74 = .text:0x801B0E74; // type:function size:0x8
-fn_801B0E7C = .text:0x801B0E7C; // type:function size:0x60
-fn_801B0EDC = .text:0x801B0EDC; // type:function size:0x18
-fn_801B0EF4 = .text:0x801B0EF4; // type:function size:0xC4
-fn_801B0FB8 = .text:0x801B0FB8; // type:function size:0xC4
-fn_801B107C = .text:0x801B107C; // type:function size:0x14C
-fn_801B11C8 = .text:0x801B11C8; // type:function size:0x10
-fn_801B11D8 = .text:0x801B11D8; // type:function size:0x1BC
-fn_801B1394 = .text:0x801B1394; // type:function size:0x40
-fn_801B13D4 = .text:0x801B13D4; // type:function size:0x40
-fn_801B1414 = .text:0x801B1414; // type:function size:0xC4
-fn_801B14D8 = .text:0x801B14D8; // type:function size:0x4
-fn_801B14DC = .text:0x801B14DC; // type:function size:0x58
-fn_801B1534 = .text:0x801B1534; // type:function size:0x40
-fn_801B1574 = .text:0x801B1574; // type:function size:0x40
-fn_801B15B4 = .text:0x801B15B4; // type:function size:0x8
-fn_801B15BC = .text:0x801B15BC; // type:function size:0x28
-fn_801B15E4 = .text:0x801B15E4; // type:function size:0x40
-fn_801B1624 = .text:0x801B1624; // type:function size:0x48
-fn_801B166C = .text:0x801B166C; // type:function size:0x4
-fn_801B1670 = .text:0x801B1670; // type:function size:0x4
-fn_801B1674 = .text:0x801B1674; // type:function size:0x44
-fn_801B16B8 = .text:0x801B16B8; // type:function size:0x40
-fn_801B16F8 = .text:0x801B16F8; // type:function size:0x8
-fn_801B1700 = .text:0x801B1700; // type:function size:0x10
-fn_801B1710 = .text:0x801B1710; // type:function size:0x30
-fn_801B1740 = .text:0x801B1740; // type:function size:0x38
-fn_801B1778 = .text:0x801B1778; // type:function size:0xD8
-fn_801B1850 = .text:0x801B1850; // type:function size:0x6C
-fn_801B18BC = .text:0x801B18BC; // type:function size:0x8
-fn_801B18C4 = .text:0x801B18C4; // type:function size:0x4C
-fn_801B1910 = .text:0x801B1910; // type:function size:0x40
-fn_801B1950 = .text:0x801B1950; // type:function size:0x8
+Draw__Q29RPGrpView12ScreenEffectFPC11RPGrpScreen = .text:0x801B046C; // type:function size:0x734
+Calc__Q29RPGrpView7ClipperFPC11RPGrpScreen = .text:0x801B0BA0; // type:function size:0x150
+Clip__9RPGrpViewCFRCQ34nw4r4math4VEC3f = .text:0x801B0CF0; // type:function size:0x184
+GetCamera__9RPGrpViewCFv = .text:0x801B0E74; // type:function size:0x8
+GetEnableCamera__9RPGrpViewCFv = .text:0x801B0E7C; // type:function size:0x60
+GetEnableScreen__9RPGrpViewCFv = .text:0x801B0EDC; // type:function size:0x18
+GetScreenToWorld__9RPGrpViewCFPQ34nw4r4math4VEC3RCQ34nw4r4math4VEC2 = .text:0x801B0EF4; // type:function size:0xC4
+GetWorldToScreen__9RPGrpViewCFPQ34nw4r4math4VEC3RCQ34nw4r4math4VEC3 = .text:0x801B0FB8; // type:function size:0xC4
+SetProjectionGX__9RPGrpViewCFv = .text:0x801B107C; // type:function size:0x14C
+AttachScreen__9RPGrpViewFP11RPGrpScreen = .text:0x801B11C8; // type:function size:0x10
+ClearBuffer__9RPGrpViewFv = .text:0x801B11D8; // type:function size:0x1BC
+PrepareDraw__9RPGrpViewFv = .text:0x801B1394; // type:function size:0x40
+Calc__9RPGrpViewFv = .text:0x801B13D4; // type:function size:0x40
+CreateScreenEffect__9RPGrpViewFv = .text:0x801B1414; // type:function size:0xC4
+Configure__9RPGrpViewFv = .text:0x801B14D8; // type:function size:0x4
+__ct__9RPGrpViewFUc = .text:0x801B14DC; // type:function size:0x58
+__dt__Q29RPGrpView12ScreenEffectFv = .text:0x801B1534; // type:function size:0x40
+__dt__9RPGrpViewFv = .text:0x801B1574; // type:function size:0x40
+AttachCamera__9RPGrpViewFP11RPGrpCamera = .text:0x801B15B4; // type:function size:0x8
+__sinit_\RPGrpView_cpp = .text:0x801B15BC; // type:function size:0x28
+__dt__Q29RPGrpView7ClipperFv = .text:0x801B15E4; // type:function size:0x40
+Draw__17RPGrpViewRender2DFv = .text:0x801B1624; // type:function size:0x48
+PrepareDraw__17RPGrpViewRender2DFv = .text:0x801B166C; // type:function size:0x4
+Configure__17RPGrpViewRender2DFv = .text:0x801B1670; // type:function size:0x4
+__ct__17RPGrpViewRender2DFUc = .text:0x801B1674; // type:function size:0x44
+__dt__17RPGrpViewRender2DFv = .text:0x801B16B8; // type:function size:0x40
+GetType__17RPGrpViewRender2DCFv = .text:0x801B16F8; // type:function size:0x8
+AttachCamera__17RPGrpViewRender3DFP11RPGrpCamera = .text:0x801B1700; // type:function size:0x10
+PrepareDrawGX__17RPGrpViewRender3DFv = .text:0x801B1710; // type:function size:0x30
+Draw__17RPGrpViewRender3DFv = .text:0x801B1740; // type:function size:0x38
+PrepareDraw__17RPGrpViewRender3DFv = .text:0x801B1778; // type:function size:0xD8
+Calc__17RPGrpViewRender3DFv = .text:0x801B1850; // type:function size:0x6C
+GetCamera__17RPGrpViewRender3DCFv = .text:0x801B18BC; // type:function size:0x8
+__ct__17RPGrpViewRender3DFUc = .text:0x801B18C4; // type:function size:0x4C
+__dt__17RPGrpViewRender3DFv = .text:0x801B1910; // type:function size:0x40
+GetType__17RPGrpViewRender3DCFv = .text:0x801B1950; // type:function size:0x8
fn_801B1958 = .text:0x801B1958; // type:function size:0x98
fn_801B19F0 = .text:0x801B19F0; // type:function size:0x24
fn_801B1A14 = .text:0x801B1A14; // type:function size:0x80
@@ -8014,7 +8014,7 @@ fn_801B1A94 = .text:0x801B1A94; // type:function size:0x18
fn_801B1AAC = .text:0x801B1AAC; // type:function size:0x14
fn_801B1AC0 = .text:0x801B1AC0; // type:function size:0x14
fn_801B1AD4 = .text:0x801B1AD4; // type:function size:0x120
-fn_801B1BF4 = .text:0x801B1BF4; // type:function size:0x50
+DrawPrepare__15RPGrpModelSceneFPC11RPGrpCameraPC11RPGrpScreen = .text:0x801B1BF4; // type:function size:0x50
fn_801B1C44 = .text:0x801B1C44; // type:function size:0x40
fn_801B1C84 = .text:0x801B1C84; // type:function size:0x100
fn_801B1D84 = .text:0x801B1D84; // type:function size:0x38
@@ -17240,8 +17240,8 @@ __vt__Q23EGG13ModelSnapshot = .data:0x80397C30; // type:object size:0x20 scope:g
@STRING@getShapeSphere__Q23EGG17ModelBoundingInfoCFv = .data:0x80397C5C; // type:object size:0x17 scope:weak data:string
@11930 = .data:0x80397C78; // type:object size:0x28 scope:local
__vt__Q23EGG14PostEffectBase = .data:0x80397CA0; // type:object size:0x24 scope:global
-lbl_80397CC8 = .data:0x80397CC8; // type:object size:0x10 data:string
-lbl_80397CD8 = .data:0x80397CD8; // type:object size:0xD data:string
+@STRING@SetProjectionType__Q23EGG7FrustumFQ33EGG7Frustum14ProjectionType@0 = .data:0x80397CC8; // type:object size:0x10 data:string
+@STRING@SetProjectionType__Q23EGG7FrustumFQ33EGG7Frustum14ProjectionType = .data:0x80397CD8; // type:object size:0xD data:string
lbl_80397CE8 = .data:0x80397CE8; // type:object size:0x28
lbl_80397D10 = .data:0x80397D10; // type:object size:0x28
lbl_80397D38 = .data:0x80397D38; // type:object size:0x28
@@ -18676,8 +18676,8 @@ lbl_803BA5B0 = .data:0x803BA5B0; // type:object size:0xD data:string
lbl_803BA5C0 = .data:0x803BA5C0; // type:object size:0x2C
lbl_803BA5EC = .data:0x803BA5EC; // type:object size:0xC
lbl_803BA5F8 = .data:0x803BA5F8; // type:object size:0x10
-lbl_803BA608 = .data:0x803BA608; // type:object size:0x30
-lbl_803BA638 = .data:0x803BA638; // type:object size:0x30
+__vt__17RPGrpViewRender2D = .data:0x803BA608; // type:object size:0x30
+__vt__17RPGrpViewRender3D = .data:0x803BA638; // type:object size:0x30
lbl_803BA668 = .data:0x803BA668; // type:object size:0x10
lbl_803BA678 = .data:0x803BA678; // type:object size:0x20
lbl_803BA698 = .data:0x803BA698; // type:object size:0x28
@@ -21903,7 +21903,7 @@ spCalcModel__10RPGrpModel = .sbss:0x804BF5E0; // type:object size:0x4 data:4byte
spCalcWorldMtxArray__10RPGrpModel = .sbss:0x804BF5E4; // type:object size:0x4 data:4byte
spCalcViewMtxArray__10RPGrpModel = .sbss:0x804BF5E8; // type:object size:0x4 data:4byte
lbl_804BF5F0 = .sbss:0x804BF5F0; // type:object size:0x8 data:byte
-lbl_804BF5F8 = .sbss:0x804BF5F8; // type:object size:0x8 data:4byte
+spCurrent__17RPGrpModelManager = .sbss:0x804BF5F8; // type:object size:0x8 data:4byte
spCurrent__20RPGrpModelResManager = .sbss:0x804BF600; // type:object size:0x8 data:4byte
lbl_804BF608 = .sbss:0x804BF608; // type:object size:0x8 data:4byte
spCurrent__13RPGrpRenderer = .sbss:0x804BF610; // type:object size:0x4 data:4byte
diff --git a/configure.py b/configure.py
index 40db118c9..07a538fff 100755
--- a/configure.py
+++ b/configure.py
@@ -1262,8 +1262,8 @@ def MatchingFor(*versions):
Object(NonMatching, "Pack/RPGraphics/RPGrpRenderer.cpp"),
Object(Matching, "Pack/RPGraphics/RPGrpScreen.cpp"),
Object(NonMatching, "Pack/RPGraphics/RPGrpView.cpp"),
- Object(NonMatching, "Pack/RPGraphics/RPGrpViewRender2D.cpp"),
- Object(NonMatching, "Pack/RPGraphics/RPGrpViewRender3D.cpp"),
+ Object(Matching, "Pack/RPGraphics/RPGrpViewRender2D.cpp"),
+ Object(Matching, "Pack/RPGraphics/RPGrpViewRender3D.cpp"),
Object(NonMatching, "Pack/RPGraphics/RPGrpModelScene.cpp"),
Object(NonMatching, "Pack/RPGraphics/RPGrpDrawPathLightMap.cpp"),
Object(Matching, "Pack/RPGraphics/RPGrpModelBoundingInfo.cpp"),
diff --git a/include/Pack/RPGraphics.h b/include/Pack/RPGraphics.h
index 75160af7b..87c6b3d33 100644
--- a/include/Pack/RPGraphics.h
+++ b/include/Pack/RPGraphics.h
@@ -27,11 +27,14 @@
#include
#include
#include
+#include
#include
#include
#include
#include
#include
#include
+#include
+#include
#endif
diff --git a/include/Pack/RPGraphics/RPGrpModelManager.h b/include/Pack/RPGraphics/RPGrpModelManager.h
index 92e4e2549..6a3f8aacf 100644
--- a/include/Pack/RPGraphics/RPGrpModelManager.h
+++ b/include/Pack/RPGraphics/RPGrpModelManager.h
@@ -7,11 +7,16 @@
// Forward declarations
class RPGrpDrawPathManager;
+class RPGrpModelScene;
/**
* @brief Model manager
*/
class RPGrpModelManager {
+public:
+ //! Maximum number of model scenes
+ static const int MAX_SCENE = 8;
+
public:
/**
* @brief Gets the currently active manager instance
@@ -22,9 +27,16 @@ class RPGrpModelManager {
RPGrpDrawPathManager* GetDrawPathManager(u8 drawScene) const;
+ RPGrpModelScene* GetModelScene(int i) {
+ return mpModelScenes[i];
+ }
+
private:
//! Allocator used for model-related allocations
static RPGrpModelManager* spCurrent;
+
+ //! Model scenes
+ RPGrpModelScene* mpModelScenes[MAX_SCENE]; // at 0x4
};
//! @}
diff --git a/include/Pack/RPGraphics/RPGrpModelScene.h b/include/Pack/RPGraphics/RPGrpModelScene.h
new file mode 100644
index 000000000..2f4fed433
--- /dev/null
+++ b/include/Pack/RPGraphics/RPGrpModelScene.h
@@ -0,0 +1,32 @@
+#ifndef RP_GRAPHICS_MODEL_SCENE_H
+#define RP_GRAPHICS_MODEL_SCENE_H
+#include
+
+//! @addtogroup rp_graphics
+//! @{
+
+// Forward declarations
+class RPGrpCamera;
+class RPGrpScreen;
+
+/**
+ * @brief Model rendering scene
+ */
+class RPGrpModelScene {
+private:
+ char unk00[0xA4];
+
+public:
+ virtual ~RPGrpModelScene(); // at 0x8
+ virtual void CalcView(); // at 0xC
+ virtual void CalcDrawList(); // at 0x10
+ virtual void Draw(); // at 0x14
+ virtual void DrawFinish(); // at 0x18
+ virtual void PreConditionForRenderingGX() const; // at 0x1C
+
+ void DrawPrepare(const RPGrpCamera* pCamera, const RPGrpScreen* pScreen);
+};
+
+//! @}
+
+#endif
diff --git a/include/Pack/RPGraphics/RPGrpRenderer.h b/include/Pack/RPGraphics/RPGrpRenderer.h
index 3f89e4912..24fd2ed83 100644
--- a/include/Pack/RPGraphics/RPGrpRenderer.h
+++ b/include/Pack/RPGraphics/RPGrpRenderer.h
@@ -36,7 +36,7 @@ class RPGrpRenderer {
}
RPGrpView* GetView(int idx) const {
- return mDrawViews[idx];
+ return mpDrawViews[idx];
}
/**
@@ -78,7 +78,7 @@ class RPGrpRenderer {
char unk0[0xC];
IRPGrpDrawObject* mpDrawList; // at 0xC
char unk10[0x14 - 0x10];
- RPGrpView* mDrawViews[MAX_VIEW]; // at 0x14
+ RPGrpView* mpDrawViews[MAX_VIEW]; // at 0x14
};
//! @}
diff --git a/include/Pack/RPGraphics/RPGrpView.h b/include/Pack/RPGraphics/RPGrpView.h
index 433a7f627..59f5ec76b 100644
--- a/include/Pack/RPGraphics/RPGrpView.h
+++ b/include/Pack/RPGraphics/RPGrpView.h
@@ -2,6 +2,10 @@
#define RP_GRAPHICS_VIEW_H
#include
+#include
+
+#include
+
//! @addtogroup rp_graphics
//! @{
@@ -9,42 +13,375 @@
class RPGrpCamera;
class RPGrpScreen;
+/**
+ * @brief Base class for renderer views
+ */
class RPGrpView {
public:
+ /**
+ * @brief View class type
+ */
+ enum EType {
+ EType_Render3D, //!< RPGrpViewRender3D
+ EType_Render2D, //!< RPGrpViewRender2D
+ };
+
+ /**
+ * @brief Projection type
+ */
enum EProjType {
- EProjType_Persp,
- EProjType_Ortho,
+ EProjType_Persp, //!< Perspective
+ EProjType_Ortho, //!< Orthographic
EProjType_Max,
};
+ /**
+ * @brief View clipper
+ */
+ class Clipper {
+ private:
+ //! Left clipping plane
+ nw4r::math::VEC3 l; // at 0x0
+ //! Top clipping plane
+ nw4r::math::VEC3 t; // at 0xC
+ //! Right clipping plane
+ nw4r::math::VEC3 r; // at 0x18
+ //! Bottom clipping plane
+ nw4r::math::VEC3 b; // at 0x24
+
+ char unk30[0x48 - 0x30];
+
+ public:
+ /**
+ * @brief Destructor
+ */
+ virtual ~Clipper() {} // at 0x8
+
+ /**
+ * @brief Re-calculates this clipper's clipping planes
+ *
+ * @param pScreen Screen rendering surface
+ */
+ void Calc(const RPGrpScreen* pScreen) DECOMP_DONT_INLINE;
+
+ /**
+ * @brief Tests whether the specified bounding sphere falls within the
+ * view frustum
+ *
+ * @param pScreen Screen rendering surface
+ * @param rPos Bounding sphere position
+ * @param radius Bounding sphere radius
+ */
+ bool Clip(const RPGrpScreen* pScreen, const nw4r::math::VEC3& rPos,
+ f32 radius);
+ };
+
+ /**
+ * @brief Screen post-effect
+ */
+ class ScreenEffect {
+ private:
+ //! Color to apply through multiply blending
+ GXColor mColorMultiply; // at 0x0
+ //! Color to apply through addition blending
+ GXColor mColorAdd; // at 0x4
+ //! Color to apply through normal blending
+ GXColor mColorBlend; // at 0x8
+
+ //! Blur effect horizontal offset
+ f32 mBlurOffset; // at 0xC
+ //! Blur effect transparency
+ u8 mBlurAlpha; // at 0x10
+
+ public:
+ /**
+ * @brief Constructor
+ */
+ ScreenEffect();
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~ScreenEffect() {} // at 0x8
+
+ /**
+ * @brief Draws this effect to the specified screen
+ *
+ * @param pScreen Screen rendering surface
+ */
+ void Draw(const RPGrpScreen* pScreen);
+
+ /**
+ * @brief Sets the color applied through multiply blending
+ *
+ * @param rColor Multiply color
+ */
+ void SetColorMultiply(const GXColor& rColor) {
+ mColorMultiply = rColor;
+ }
+
+ /**
+ * @brief Sets the color applied through addition blending
+ *
+ * @param rColor Addition color
+ */
+ void SetColorAdd(const GXColor& rColor) {
+ mColorAdd = rColor;
+ }
+
+ /**
+ * @brief Sets the color applied through normal blending
+ *
+ * @param rColor Normal blend color
+ */
+ void SetColorBlend(const GXColor& rColor) {
+ mColorBlend = rColor;
+ }
+
+ /**
+ * @brief Sets the horizontal offset of the blur effect's copies
+ *
+ * @param offset Horizontal offset
+ */
+ void SetBlurOffset(f32 offset) {
+ mBlurOffset = offset;
+ }
+
+ /**
+ * @brief Sets the transparency of the blur effect
+ *
+ * @param alpha Blur effect transparency
+ */
+ void SetBlurAlpha(u8 alpha) {
+ mBlurAlpha = alpha;
+ }
+ };
+
protected:
- u8 mViewNo; // at 0x0
+ /**
+ * @brief Renderer view flags
+ */
+ enum {
+ //! View will be updated and rendered
+ EFlag_SysCalc = 1 << 0,
+
+ //! Update color when clearing the framebuffer
+ EFlag_FillBufferColor = 1 << 1,
+ //! Update alpha when clearing the framebuffer
+ EFlag_FillBufferAlpha = 1 << 2,
+ //! Update depth when clearing the framebuffer
+ EFlag_FillBufferTexture = 1 << 3,
+
+ EFlag_SysDraw = 1 << 4,
+ EFlag_9 = 1 << 9,
+ };
+
+protected:
+ //! Renderer view ID
+ u8 mViewNo; // at 0x0
+ //! Model scene ID
u8 mDrawScene; // at 0x1
- char unk2[0x8 - 0x2];
+ char unk2[0x4 - 0x2];
+
+ //! Renderer view flags
+ u16 mFlags; // at 0x4
+
+ //! Projection type
EProjType mProjType; // at 0x8
- char unkC[0x10 - 0xC];
+ //! Framebuffer clear color
+ GXColor mClearColor; // at 0xC
+
+ //! Screen rendering surface
RPGrpScreen* mpScreen; // at 0x10
- char unk14[0x1C - 0x14];
+ u32 unk14;
+ //! Screen post-effect
+ ScreenEffect* mpScreenEffect; // at 0x18
+
+private:
+ //! Default framebuffer clear color
+ static GXColor DEFAULT_CLEAR_COLOR;
+
+ //! View clipper instance
+ static Clipper sClipper;
public:
- virtual ~RPGrpView(); // at 0x8
- virtual UNKTYPE VF_0xC(UNKTYPE) = 0; // at 0xC
- virtual void AttachCamera(RPGrpCamera* pCamera) = 0; // at 0x10
+ /**
+ * @brief Constructor
+ *
+ * @param no View ID
+ */
+ explicit RPGrpView(u8 no);
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~RPGrpView() {} // at 0x8
+
+ /**
+ * @brief Gets the type of this view
+ */
+ virtual EType GetType() const = 0; // at 0xC
+
+ /**
+ * @brief Attaches a new camera to this view
+ *
+ * @param pCamera New camera
+ * @return Previously attached camera
+ */
+ virtual RPGrpCamera* AttachCamera(RPGrpCamera* /* pCamera */) { // at 0x10
+ return NULL;
+ }
+
+ /**
+ * @brief Gets the camera currently attached to this view
+ */
+ virtual RPGrpCamera* GetCamera() const { // at 0x14
+ return NULL;
+ }
+
+ /**
+ * @brief Initializes this view's state
+ */
+ virtual void Configure(); // at 0x18
+
+ /**
+ * @brief Updates this view's state
+ */
+ virtual void Calc(); // at 0x1C
+
+ /**
+ * @brief Prepares this view for a new frame
+ */
+ virtual void PrepareDraw(); // at 0x20
+
+ /**
+ * @brief Renders the contents of this view
+ */
+ virtual void Draw() = 0; // at 0x24
+
+ /**
+ * @brief Prepares this view for a new render pass
+ */
+ virtual void PrepareDrawGX() {
+ SetProjectionGX();
+ } // at 0x28
+
+ /**
+ * @brief Attaches a screen effect to this view
+ */
+ void CreateScreenEffect();
+
+ /**
+ * @brief Clears the framebuffer of the attached screen
+ */
+ void ClearBuffer();
+ /**
+ * @brief Attaches a new screen to this view
+ *
+ * @param pScreen Screen rendering surface
+ * @return Previously attached screen
+ */
+ RPGrpScreen* AttachScreen(RPGrpScreen* pScreen);
+
+ /**
+ * @brief Configures the GX projection matrix
+ */
+ void SetProjectionGX() const;
+
+ /**
+ * @brief Converts a position from world-space to screen-space
+ *
+ * @param[out] pScreenPos Position in screen-space
+ * @param rWorldPos Position in world-space
+ */
+ void GetWorldToScreen(nw4r::math::VEC3* pScreenPos,
+ const nw4r::math::VEC3& rWorldPos) const;
+
+ /**
+ * @brief Converts a position from screen-space to world-space
+ *
+ * @param[out] pWorldPos Position in world-space
+ * @param rScreenPos Position in screen-space
+ */
+ void GetScreenToWorld(nw4r::math::VEC3* pWorldPos,
+ const nw4r::math::VEC2& rScreenPos) const;
+
+ /**
+ * @brief Gets the screen used by this view.
+ * @details If no screen is attached, this function returns the root screen.
+ */
+ RPGrpScreen* GetEnableScreen() const;
+
+ /**
+ * @brief Gets the camera used by this view.
+ * @details If no camera is attached, this function returns the default
+ * camera.
+ */
+ RPGrpCamera* GetEnableCamera() const;
+
+ /**
+ * @brief Tests whether the specified bounding sphere falls within the
+ * view frustum
+ *
+ * @param pScreen Screen rendering surface
+ * @param rPos Bounding sphere position
+ * @param radius Bounding sphere radius
+ */
+ bool Clip(const nw4r::math::VEC3& rPos, f32 radius) const;
+
+ /**
+ * @brief Sets this view's model scene
+ *
+ * @param scene Model scene ID
+ */
void SetDrawScene(u8 scene) {
mDrawScene = scene;
}
+ /**
+ * @brief Tests whether this view should be updated
+ */
+ bool IsSysCalc() const {
+ return mFlags & EFlag_SysCalc;
+ }
+
+ /**
+ * @brief Tests whether this view should be rendered
+ */
+ bool IsSysDraw() const {
+ return mFlags & EFlag_SysDraw;
+ }
+
+ /**
+ * @brief Gets this view's projection type
+ *
+ * @return EProjType
+ */
EProjType GetProjType() const {
return mProjType;
}
+ /**
+ * @brief Get this view's framebuffer clear color
+ */
+ GXColor GetClearColor() const {
+ return mClearColor;
+ }
+
+ /**
+ * @brief Gets the screen attached to this view
+ */
RPGrpScreen* GetScreen() const {
return mpScreen;
}
-private:
- ;
+ /**
+ * @brief Gets this view's screen post-effect
+ */
+ ScreenEffect* GetScreenEffect() const {
+ return mpScreenEffect;
+ }
};
//! @}
diff --git a/include/Pack/RPGraphics/RPGrpViewRender2D.h b/include/Pack/RPGraphics/RPGrpViewRender2D.h
new file mode 100644
index 000000000..ed60df01c
--- /dev/null
+++ b/include/Pack/RPGraphics/RPGrpViewRender2D.h
@@ -0,0 +1,47 @@
+#ifndef RP_GRAPHICS_VIEW_RENDER_2D_H
+#define RP_GRAPHICS_VIEW_RENDER_2D_H
+#include
+
+#include
+
+//! @addtogroup rp_graphics
+//! @{
+
+/**
+ * @brief Renderer view for 2D graphics
+ */
+class RPGrpViewRender2D : public RPGrpView {
+public:
+ /**
+ * @brief Constructor
+ *
+ * @param no View ID
+ */
+ explicit RPGrpViewRender2D(u8 no);
+
+ /**
+ * @brief Gets the type of this view
+ */
+ virtual EType GetType() const override { // at 0xC
+ return EType_Render2D;
+ }
+
+ /**
+ * @brief Initializes this view's state
+ */
+ virtual void Configure() override; // at 0x18
+
+ /**
+ * @brief Prepares this view for a new frame
+ */
+ virtual void PrepareDraw() override; // at 0x20
+
+ /**
+ * @brief Renders the contents of this view
+ */
+ virtual void Draw() override; // at 0x24
+};
+
+//! @}
+
+#endif
diff --git a/include/Pack/RPGraphics/RPGrpViewRender3D.h b/include/Pack/RPGraphics/RPGrpViewRender3D.h
new file mode 100644
index 000000000..8eb316e79
--- /dev/null
+++ b/include/Pack/RPGraphics/RPGrpViewRender3D.h
@@ -0,0 +1,76 @@
+#ifndef RP_GRAPHICS_VIEW_RENDER_3D_H
+#define RP_GRAPHICS_VIEW_RENDER_3D_H
+#include
+
+#include
+
+//! @addtogroup rp_graphics
+//! @{
+
+// Forward declarations
+class RPGrpCamera;
+
+/**
+ * @brief Renderer view for 3D graphics
+ */
+class RPGrpViewRender3D : public RPGrpView {
+public:
+ /**
+ * @brief Constructor
+ *
+ * @param no View ID
+ */
+ explicit RPGrpViewRender3D(u8 no);
+
+ /**
+ * @brief Gets the type of this view
+ */
+ virtual EType GetType() const override { // at 0xC
+ return EType_Render3D;
+ }
+
+ /**
+ * @brief Attaches a new camera to this view
+ *
+ * @param pCamera New camera
+ * @return Previously attached camera
+ */
+ virtual RPGrpCamera* AttachCamera(RPGrpCamera* pCamera) override;
+
+ /**
+ * @brief Gets the camera currently attached to this view
+ */
+ virtual RPGrpCamera* GetCamera() const override { // at 0x14
+ return mpCamera;
+ }
+
+ /**
+ * @brief Updates this view's state
+ */
+ virtual void Calc() override; // at 0x1C
+
+ /**
+ * @brief Prepares this view for a new frame
+ */
+ virtual void PrepareDraw() override; // at 0x20
+
+ /**
+ * @brief Renders the contents of this view
+ */
+ virtual void Draw() override; // at 0x24
+
+ /**
+ * @brief Prepares this view for a new render pass
+ */
+ virtual void PrepareDrawGX() override; // at 0x28
+
+private:
+ //! Camera attached to this view
+ RPGrpCamera* mpCamera; // at 0x20
+
+ u8 unk24;
+};
+
+//! @}
+
+#endif
diff --git a/include/Pack/RPKernel/RPSysEffectCreator.h b/include/Pack/RPKernel/RPSysEffectCreator.h
index 91ba2fc95..e2e288b62 100644
--- a/include/Pack/RPKernel/RPSysEffectCreator.h
+++ b/include/Pack/RPKernel/RPSysEffectCreator.h
@@ -150,9 +150,10 @@ class RPSysEffectCreator : public EGG::Disposer {
RPSysEffectMemoryManager* mpMemoryManager; // at 0x30
//! Emitter parameter save buffers
- nw4r::ef::EmitterParameter* mEmitterParamSave[ESaveBuffer_Max]; // at 0x34
+ nw4r::ef::EmitterParameter* mpEmitterParamSave[ESaveBuffer_Max]; // at 0x34
//! Particle parameter save buffers
- nw4r::ef::ParticleParameter* mParticleParamSave[ESaveBuffer_Max]; // at 0x3C
+ nw4r::ef::ParticleParameter*
+ mpParticleParamSave[ESaveBuffer_Max]; // at 0x3C
};
//! @}
diff --git a/include/Pack/RPKernel/RPSysEffectMgr.h b/include/Pack/RPKernel/RPSysEffectMgr.h
index bd5a85d03..8af7feac9 100644
--- a/include/Pack/RPKernel/RPSysEffectMgr.h
+++ b/include/Pack/RPKernel/RPSysEffectMgr.h
@@ -123,12 +123,11 @@ class RPSysEffectMgr : public IRPSysHostIOSocket {
/**
* @brief Draws the specified set of effects
*
- * @param rDrawInfo Graphics configuration
+ * @param rViewMtx View matrix
* @param drawGroup Effect draw group
* @param drawScene Effect draw scene
*/
- void draw(const nw4r::ef::DrawInfo& rDrawInfo, u32 drawGroup,
- u32 drawScene);
+ void draw(const nw4r::math::MTX34& rViewMtx, u32 drawGroup, u32 drawScene);
/**
* @brief Creates an instance of the specified effect
diff --git a/include/egg/gfxe.h b/include/egg/gfxe.h
index 9605a9aa8..10e080d69 100644
--- a/include/egg/gfxe.h
+++ b/include/egg/gfxe.h
@@ -26,6 +26,9 @@
#include
#include
#include
+#include
+#include
+#include
#include
#include
#include
diff --git a/include/egg/gfxe/eggCapTexture.h b/include/egg/gfxe/eggCapTexture.h
index c8e74b6a6..78a1199ae 100644
--- a/include/egg/gfxe/eggCapTexture.h
+++ b/include/egg/gfxe/eggCapTexture.h
@@ -19,6 +19,9 @@ class CapTexture : public CpuTexture {
void capture(u16 x, u16 y, bool mipmap = false, int format = -1);
+ void setLoadMap(GXTexMapID loadMap) {
+ mLoadMap = loadMap;
+ }
GXTexMapID getLoadMap() const {
return mLoadMap;
}
diff --git a/include/egg/gfxe/eggFrustum.h b/include/egg/gfxe/eggFrustum.h
index fba86ab20..aa272255f 100644
--- a/include/egg/gfxe/eggFrustum.h
+++ b/include/egg/gfxe/eggFrustum.h
@@ -188,6 +188,10 @@ class Frustum {
mTanFovY = sin / cos;
}
+ f32 GetTanFovy() const {
+ return mTanFovY;
+ }
+
f32 GetNearZ() const {
return mNearZ;
}
diff --git a/include/egg/gfxe/eggPostEffectBlurSimple.h b/include/egg/gfxe/eggPostEffectBlurSimple.h
new file mode 100644
index 000000000..011661b7b
--- /dev/null
+++ b/include/egg/gfxe/eggPostEffectBlurSimple.h
@@ -0,0 +1,21 @@
+#ifndef EGG_GFXE_POST_EFFECT_BLUR_SIMPLE_H
+#define EGG_GFXE_POST_EFFECT_BLUR_SIMPLE_H
+#include "eggPostEffectBase.h"
+#include "types_egg.h"
+
+namespace EGG {
+
+class PostEffectBlurSimple : public PostEffectBase {
+public:
+ PostEffectBlurSimple();
+ virtual ~PostEffectBlurSimple() {} // at 0x8
+ virtual void reset(); // at 0x14
+ virtual void setMaterialInternal(); // at 0x18
+
+public:
+ char unk20[0x34 - 0x20];
+};
+
+} // namespace EGG
+
+#endif
diff --git a/include/egg/gfxe/eggScreen.h b/include/egg/gfxe/eggScreen.h
index b32d3f1f7..d3587f86d 100644
--- a/include/egg/gfxe/eggScreen.h
+++ b/include/egg/gfxe/eggScreen.h
@@ -58,7 +58,7 @@ class Screen : public Frustum {
void CalcMatrixForDrawQuad(nw4r::math::MTX34* pMtx, f32 x, f32 y, f32 width,
f32 height) const;
- void FillBufferGX(u32 flags, GXColor color, u32 arg2) const;
+ void FillBufferGX(u32 flags, GXColor color, u32 arg2 = 0) const;
void GetGlobalPos(f32* pX, f32* pY) const;
const Screen* GetParent() const {
diff --git a/include/egg/gfxe/eggStateGX.h b/include/egg/gfxe/eggStateGX.h
index 023b298b8..51f2d36c8 100644
--- a/include/egg/gfxe/eggStateGX.h
+++ b/include/egg/gfxe/eggStateGX.h
@@ -127,11 +127,19 @@ class StateGX {
cCacheFlag_AlphaUpdate = 1 << 6,
};
+ // TODO(kiwi) Add flag inlines
+public:
enum {
+ cFlag_0 = 1 << 0,
+ cFlag_1 = 1 << 1,
cFlag_EnableTMem = 1 << 4,
cFlag_EnableCache = 1 << 5,
};
+ // TODO(kiwi) Add flag inlines
+public:
+ static u16 s_flag;
+
private:
static GXCache s_cacheGX;
@@ -146,8 +154,6 @@ class StateGX {
static GXColor s_clearEfb;
- static u16 s_flag;
-
static f32 s_modifyRatio;
static nw4r::g3d::tmem::TMemLayout s_tmem_layout;
diff --git a/src/Pack/RPGraphics/RPGrpView.cpp b/src/Pack/RPGraphics/RPGrpView.cpp
new file mode 100644
index 000000000..f517faad4
--- /dev/null
+++ b/src/Pack/RPGraphics/RPGrpView.cpp
@@ -0,0 +1,435 @@
+#include
+
+#include
+
+#include
+
+#include
+
+/******************************************************************************
+ *
+ * RPGrpView
+ *
+ ******************************************************************************/
+
+/**
+ * @brief Default framebuffer clear color
+ */
+GXColor RPGrpView::DEFAULT_CLEAR_COLOR = {0, 0, 0, 255};
+
+/**
+ * @brief View clipper instance
+ */
+RPGrpView::Clipper RPGrpView::sClipper;
+
+/**
+ * @brief Constructor
+ *
+ * @param no View ID
+ */
+RPGrpView::RPGrpView(u8 no)
+ : mViewNo(no),
+ mDrawScene(0),
+ mFlags(EFlag_9 | EFlag_SysDraw | EFlag_SysCalc),
+ mProjType(EProjType_Max),
+ mClearColor(DEFAULT_CLEAR_COLOR),
+ mpScreen(NULL),
+ unk14(0),
+ mpScreenEffect(NULL) {}
+
+/**
+ * @brief Initializes this view's state
+ */
+void RPGrpView::Configure() {}
+
+/**
+ * @brief Attaches a screen effect to this view
+ */
+void RPGrpView::CreateScreenEffect() {
+ mpScreenEffect = new ScreenEffect();
+}
+
+/**
+ * @brief Updates this view's state
+ */
+void RPGrpView::Calc() {
+ RPGrpView::PrepareDraw();
+}
+
+/**
+ * @brief Prepares this view for a new frame
+ */
+void RPGrpView::PrepareDraw() {
+ if (!IsSysCalc()) {
+ return;
+ }
+
+ if (mProjType == EProjType_Persp) {
+ sClipper.Calc(GetEnableScreen());
+ }
+}
+
+/**
+ * @brief Clears the framebuffer of the attached screen
+ */
+void RPGrpView::ClearBuffer() {
+ GXColor clearColor = EGG::StateGX::getEfbClearColor();
+ u8 flags = 0;
+
+ if (mFlags & EFlag_FillBufferColor) {
+ clearColor.r = GetClearColor().r;
+ clearColor.g = GetClearColor().g;
+ clearColor.b = GetClearColor().b;
+
+ flags |= EGG::Screen::FILLBUFFER_COLOR;
+ EGG::StateGX::s_flag |= EGG::StateGX::cFlag_0;
+ } else {
+ EGG::StateGX::s_flag &= ~EGG::StateGX::cFlag_0;
+ }
+
+ if (mFlags & EFlag_FillBufferAlpha) {
+ clearColor.a = GetClearColor().a;
+
+ flags |= EGG::Screen::FILLBUFFER_ALPHA;
+ EGG::StateGX::s_flag |= EGG::StateGX::cFlag_1;
+ } else {
+ EGG::StateGX::s_flag &= ~EGG::StateGX::cFlag_1;
+ }
+
+ if (mFlags & EFlag_FillBufferTexture) {
+ flags |= EGG::Screen::FILLBUFFER_TEXTURE;
+ }
+
+ if (flags != 0) {
+ GetEnableScreen()->FillBufferGX(flags, GetClearColor());
+ EGG::StateGX::setEfbClearColor(clearColor);
+ }
+
+ if (mpScreenEffect != NULL) {
+ mpScreenEffect->Draw(GetEnableScreen());
+ }
+}
+
+/**
+ * @brief Attaches a new screen to this view
+ *
+ * @param pScreen Screen rendering surface
+ * @return Previously attached screen
+ */
+RPGrpScreen* RPGrpView::AttachScreen(RPGrpScreen* pScreen) {
+ RPGrpScreen* pOldScreen = mpScreen;
+ mpScreen = pScreen;
+ return pOldScreen;
+}
+
+/**
+ * @brief Configures the GX projection matrix
+ */
+void RPGrpView::SetProjectionGX() const {
+ EGG::DrawGX::SetCameraMtx(GetEnableCamera()->GetSavedCameraMatrix());
+
+ EGG::Screen clone(*GetEnableScreen());
+
+ switch (mProjType) {
+ case EProjType_Persp: {
+ clone.SetProjectionType(EGG::Screen::PROJ_PERSP);
+ break;
+ }
+
+ case EProjType_Ortho: {
+ if (GetType() == EType_Render2D) {
+ clone.SetNearZ(-10000.0f);
+ clone.SetFarZ(10000.0f);
+ }
+
+ clone.SetProjectionType(EGG::Screen::PROJ_ORTHO);
+ break;
+ }
+
+ default: {
+ break;
+ }
+ }
+
+ clone.SetProjectionGX();
+}
+
+/**
+ * @brief Converts a position from world-space to screen-space
+ *
+ * @param[out] pScreenPos Position in screen-space
+ * @param rWorldPos Position in world-space
+ */
+void RPGrpView::GetWorldToScreen(nw4r::math::VEC3* pScreenPos,
+ const nw4r::math::VEC3& rWorldPos) const {
+ if (GetCamera() != NULL) {
+ GetCamera()->GetWorldToScreen(pScreenPos, rWorldPos, GetEnableScreen());
+ } else {
+ GetEnableScreen()->GetViewToScreen(pScreenPos, rWorldPos);
+ }
+}
+
+/**
+ * @brief Converts a position from screen-space to world-space
+ *
+ * @param[out] pWorldPos Position in world-space
+ * @param rScreenPos Position in screen-space
+ */
+void RPGrpView::GetScreenToWorld(nw4r::math::VEC3* pWorldPos,
+ const nw4r::math::VEC2& rScreenPos) const {
+ if (GetCamera() != NULL) {
+ GetCamera()->GetScreenToWorld(pWorldPos, rScreenPos, GetEnableScreen());
+ } else {
+ GetEnableScreen()->GetScreenToView(pWorldPos, rScreenPos);
+ }
+}
+
+/**
+ * @brief Gets the screen used by this view.
+ * @details If no screen is attached, this function returns the root screen.
+ */
+RPGrpScreen* RPGrpView::GetEnableScreen() const {
+ if (GetScreen() != NULL) {
+ return GetScreen();
+ }
+
+ return &RPGrpScreen::GetRootScreen();
+}
+
+/**
+ * @brief Gets the camera used by this view.
+ * @details If no camera is attached, this function returns the default
+ * camera.
+ */
+RPGrpCamera* RPGrpView::GetEnableCamera() const {
+ if (GetCamera() != NULL) {
+ return GetCamera();
+ }
+
+ return &RPGrpCamera::GetDefaultCamera();
+}
+
+/**
+ * @brief Tests whether the specified bounding sphere falls within the
+ * view frustum
+ *
+ * @param pScreen Screen rendering surface
+ * @param rPos Bounding sphere position
+ * @param radius Bounding sphere radius
+ */
+bool RPGrpView::Clip(const nw4r::math::VEC3& rPos, f32 radius) const {
+ nw4r::math::VEC3 local;
+ nw4r::math::VEC3TransformCoord(
+ &local, &GetEnableCamera()->GetSavedCameraMatrix(), &rPos);
+
+ return sClipper.Clip(GetEnableScreen(), local, radius);
+}
+
+/******************************************************************************
+ *
+ * Clipper
+ *
+ ******************************************************************************/
+
+/**
+ * @brief Re-calculates this clipper's clipping planes
+ *
+ * @param pScreen Screen rendering surface
+ */
+void RPGrpView::Clipper::Calc(const RPGrpScreen* pScreen) {
+ f32 ny = pScreen->GetNearZ() * pScreen->GetTanFovy();
+ f32 nx = ny * pScreen->GetWidth() / pScreen->GetHeight();
+
+ nw4r::math::VEC3 bl(-nx, -ny, -pScreen->GetNearZ());
+ nw4r::math::VEC3 tl(-nx, ny, -pScreen->GetNearZ());
+ nw4r::math::VEC3 tr(nx, ny, -pScreen->GetNearZ());
+ nw4r::math::VEC3 br(nx, -ny, -pScreen->GetNearZ());
+
+ nw4r::math::VEC3Cross(&l, &tl, &bl);
+ nw4r::math::VEC3Cross(&t, &tr, &tl);
+ nw4r::math::VEC3Cross(&r, &br, &tr);
+ nw4r::math::VEC3Cross(&b, &bl, &br);
+
+ nw4r::math::VEC3Normalize(&l, &l);
+ nw4r::math::VEC3Normalize(&t, &t);
+ nw4r::math::VEC3Normalize(&r, &r);
+ nw4r::math::VEC3Normalize(&b, &b);
+}
+
+/**
+ * @brief Tests whether the specified bounding sphere falls within the
+ * view frustum
+ *
+ * @param pScreen Screen rendering surface
+ * @param rPos Bounding sphere position
+ * @param radius Bounding sphere radius
+ */
+bool RPGrpView::Clipper::Clip(const RPGrpScreen* pScreen,
+ const nw4r::math::VEC3& rPos, f32 radius) {
+
+ if (-rPos.z < pScreen->GetNearZ() - radius ||
+ -rPos.z > pScreen->GetFarZ() + radius) {
+
+ return true;
+ }
+
+ if (rPos.x * l.x + rPos.y * l.y + rPos.z * l.z > radius) {
+ return true;
+ }
+
+ if (rPos.x * t.x + rPos.y * t.y + rPos.z * t.z > radius) {
+ return true;
+ }
+
+ if (rPos.x * r.x + rPos.y * r.y + rPos.z * r.z > radius) {
+ return true;
+ }
+
+ if (rPos.x * b.x + rPos.y * b.y + rPos.z * b.z > radius) {
+ return true;
+ }
+
+ return false;
+}
+
+/******************************************************************************
+ *
+ * ScreenEffect
+ *
+ ******************************************************************************/
+
+/**
+ * @brief Constructor
+ */
+RPGrpView::ScreenEffect::ScreenEffect() {
+ mColorMultiply = EGG::DrawGX::WHITE;
+ mColorAdd = EGG::DrawGX::BLACK;
+ mColorBlend = (GXColor){0, 0, 0, 0};
+
+ mBlurOffset = 1.2f;
+ mBlurAlpha = 0;
+}
+
+/**
+ * @brief Draws this effect to the specified screen
+ *
+ * @param pScreen Screen rendering surface
+ */
+void RPGrpView::ScreenEffect::Draw(const RPGrpScreen* pScreen) {
+ bool needBlur = mBlurAlpha > 0;
+
+ bool needMul = mColorMultiply.r != 255 || mColorMultiply.g != 255 ||
+ mColorMultiply.b != 255;
+
+ bool needAdd = (mColorAdd.r != 0 || mColorAdd.g != 0 || mColorAdd.b != 0) &&
+ mColorAdd.a > 0;
+
+ bool needNormal = mColorBlend.a > 0;
+
+ if (needBlur || needMul || needAdd || needNormal) {
+ EGG::StateGX::GXSetColorUpdate_(true);
+ EGG::StateGX::GXSetAlphaUpdate_(false);
+
+ GXInvalidateTexAll();
+
+ EGG::Screen clone(*pScreen);
+ clone.SetNearZ(0.0f);
+ clone.SetFarZ(1.0f);
+ clone.SetCanvasMode(EGG::Screen::CANVAS_LU);
+ clone.SetProjectionType(EGG::Screen::PROJ_ORTHO);
+ clone.SetProjectionGX();
+
+ const EGG::Screen::DataEfb& rEfb = pScreen->GetDataEfb();
+ u16 x = static_cast(rEfb.vp.x);
+ u16 y = static_cast(rEfb.vp.y);
+ // Downscaled for mipmapping
+ u16 halfWidth = static_cast(rEfb.vp.width / 2);
+ u16 halfHeight = static_cast(rEfb.vp.height / 2);
+
+ if (needBlur) {
+ // Screenshot used as a base for blurring
+ EGG::TextureBuffer* pScreenCapture = EGG::TextureBuffer::alloc( //
+ halfWidth, //
+ halfHeight, //
+ GX_TF_RGBA8);
+
+ // Backup of original pixels that will be clobbered by blurring
+ EGG::TextureBuffer* pScreenBackup = EGG::TextureBuffer::alloc( //
+ halfWidth / 2, //
+ halfHeight / 2, //
+ GX_TF_RGBA8);
+
+ // Blur posteffect result in texture form
+ EGG::TextureBuffer* pEffectCapture = EGG::TextureBuffer::alloc( //
+ halfWidth / 2, //
+ halfHeight / 2, //
+ GX_TF_RGBA8);
+
+ // Save the appearance of the screen space
+ // that will be overwritten by the blur posteffect.
+ pScreenBackup->capture(x, y);
+
+ // Take a screenshot to use as a base for blurring
+ pScreenCapture->setVFilterBlur();
+ pScreenCapture->capture(x, y, true);
+
+ // TODO(kiwi) PostEffectBlurSimple needs work
+ EGG::PostEffectBlurSimple eff;
+ eff.configure();
+ eff.setBlendMode(EGG::PostEffectBase::cBlendMode_None);
+ eff.setCapTexture(pScreenCapture);
+
+ // Draw the result of the blur posteffect (downscaled)
+ pScreenCapture->setLoadMap(GX_TEXMAP0);
+ eff.draw(pScreen->GetWidth() / 4.0f, pScreen->GetHeight() / 4.0f);
+
+ // Capture the posteffect result as a new texture
+ pEffectCapture->setVFilterBlur();
+ pEffectCapture->capture(x, y);
+
+ nw4r::math::MTX34 proj;
+ EGG::DrawGX::BeginDrawScreen(true, true, true);
+
+ // Restore the pixels overwritten by the posteffect work
+ PSMTXScale( //
+ proj, //
+ pScreen->GetWidth() / 4.0f, //
+ pScreen->GetHeight() / 4.0f, //
+ 1.0f);
+ pScreenBackup->load(GX_TEXMAP0);
+ EGG::DrawGX::DrawScreenTexture(proj, EGG::DrawGX::WHITE);
+
+ // Upscale the blur effect to the entire screen
+ PSMTXScale(proj, pScreen->GetWidth(), pScreen->GetHeight(), 1.0f);
+ pEffectCapture->load(GX_TEXMAP0);
+ GXColor color = (GXColor){255, 255, 255, mBlurAlpha};
+ EGG::DrawGX::DrawScreenTexture(proj, color);
+
+ pScreenBackup->free();
+ pScreenCapture->free();
+ pEffectCapture->free();
+ }
+
+ if (needMul || needAdd || needNormal) {
+ EGG::DrawGX::BeginDrawScreen(true, false, false);
+
+ nw4r::math::MTX34 proj;
+ PSMTXScale(proj, pScreen->GetWidth(), pScreen->GetHeight(), 1.0f);
+
+ if (needMul) {
+ EGG::DrawGX::SetBlendMode(EGG::DrawGX::BLEND_MUL);
+ EGG::DrawGX::DrawScreen(proj, mColorMultiply);
+ }
+
+ if (needAdd) {
+ EGG::DrawGX::SetBlendMode(EGG::DrawGX::BLEND_ADD_ALPHA);
+ EGG::DrawGX::DrawScreen(proj, mColorAdd);
+ }
+
+ if (needNormal) {
+ EGG::DrawGX::SetBlendMode(EGG::DrawGX::BLEND_NORMAL);
+ EGG::DrawGX::DrawScreen(proj, mColorBlend);
+ }
+ }
+ }
+}
diff --git a/src/Pack/RPGraphics/RPGrpViewRender2D.cpp b/src/Pack/RPGraphics/RPGrpViewRender2D.cpp
new file mode 100644
index 000000000..693f0de52
--- /dev/null
+++ b/src/Pack/RPGraphics/RPGrpViewRender2D.cpp
@@ -0,0 +1,35 @@
+#include
+
+/**
+ * @brief Constructor
+ *
+ * @param no View ID
+ */
+RPGrpViewRender2D::RPGrpViewRender2D(u8 no) : RPGrpView(no) {
+ mProjType = EProjType_Ortho;
+}
+
+/**
+ * @brief Initializes this view's state
+ */
+void RPGrpViewRender2D::Configure() {}
+
+/**
+ * @brief Prepares this view for a new frame
+ */
+void RPGrpViewRender2D::PrepareDraw() {
+ RPGrpView::PrepareDraw();
+}
+
+/**
+ * @brief Renders the contents of this view
+ */
+void RPGrpViewRender2D::Draw() {
+ if (!IsSysCalc()) {
+ return;
+ }
+
+ ClearBuffer();
+ SetProjectionGX();
+ EGG::StateGX::GXSetAlphaUpdate_(false);
+}
diff --git a/src/Pack/RPGraphics/RPGrpViewRender3D.cpp b/src/Pack/RPGraphics/RPGrpViewRender3D.cpp
new file mode 100644
index 000000000..da7b70c46
--- /dev/null
+++ b/src/Pack/RPGraphics/RPGrpViewRender3D.cpp
@@ -0,0 +1,101 @@
+#include
+
+/**
+ * @brief Constructor
+ *
+ * @param no View ID
+ */
+RPGrpViewRender3D::RPGrpViewRender3D(u8 no)
+ : RPGrpView(no), mpCamera(NULL), unk24(0) {
+
+ mProjType = EProjType_Persp;
+}
+
+/**
+ * @brief Updates this view's state
+ */
+void RPGrpViewRender3D::Calc() {
+ RPGrpView::Calc();
+
+ if (!IsSysCalc()) {
+ return;
+ }
+
+ if (GetCamera() == NULL) {
+ return;
+ }
+
+ GetCamera()->SaveCameraMatrix();
+}
+
+/**
+ * @brief Prepares this view for a new frame
+ */
+void RPGrpViewRender3D::PrepareDraw() {
+ RPGrpView::PrepareDraw();
+
+ if (!IsSysCalc()) {
+ return;
+ }
+
+ ClearBuffer();
+
+ if (!IsSysDraw()) {
+ return;
+ }
+
+ RPGrpModelScene* pModelScene =
+ RPGrpModelManager::GetCurrent()->GetModelScene(mDrawScene);
+
+ RPGrpScreen clone(*GetEnableScreen());
+
+ clone.SetProjectionType(mProjType == EProjType_Persp
+ ? EGG::Screen::PROJ_PERSP
+ : EGG::Screen::PROJ_ORTHO);
+
+ pModelScene->DrawPrepare(GetEnableCamera(), &clone);
+}
+
+/**
+ * @brief Renders the contents of this view
+ */
+void RPGrpViewRender3D::Draw() {
+ if (!IsSysCalc()) {
+ return;
+ }
+
+ if (!IsSysDraw()) {
+ return;
+ }
+
+ RPGrpModelScene* pModelScene =
+ RPGrpModelManager::GetCurrent()->GetModelScene(mDrawScene);
+
+ pModelScene->Draw();
+}
+
+/**
+ * @brief Prepares this view for a new render pass
+ */
+void RPGrpViewRender3D::PrepareDrawGX() {
+ if (IsSysDraw()) {
+ RPGrpModelScene* pModelScene =
+ RPGrpModelManager::GetCurrent()->GetModelScene(mDrawScene);
+
+ pModelScene->PreConditionForRenderingGX();
+ } else {
+ SetProjectionGX();
+ }
+}
+
+/**
+ * @brief Attaches a new camera to this view
+ *
+ * @param pCamera New camera
+ * @return Previously attached camera
+ */
+RPGrpCamera* RPGrpViewRender3D::AttachCamera(RPGrpCamera* pCamera) {
+ RPGrpCamera* pOldCamera = mpCamera;
+ mpCamera = pCamera;
+ return pOldCamera;
+}
diff --git a/src/Pack/RPKernel/RPSysEffectCreator.cpp b/src/Pack/RPKernel/RPSysEffectCreator.cpp
index 43225eb4f..2616be11e 100644
--- a/src/Pack/RPKernel/RPSysEffectCreator.cpp
+++ b/src/Pack/RPKernel/RPSysEffectCreator.cpp
@@ -31,8 +31,8 @@ RPSysEffectCreator::RPSysEffectCreator(u32 drawScene) {
mpMemoryManager = NULL;
for (int i = 0; i < ESaveBuffer_Max; i++) {
- mEmitterParamSave[i] = NULL;
- mParticleParamSave[i] = NULL;
+ mpEmitterParamSave[i] = NULL;
+ mpParticleParamSave[i] = NULL;
}
}
@@ -116,9 +116,9 @@ void RPSysEffectCreator::createSlowSystem() {
RPSysEffectDefine::MAX_GROUP_ID);
for (int i = 0; i < ESaveBuffer_Max; i++) {
- mEmitterParamSave[i] = //
+ mpEmitterParamSave[i] = //
new nw4r::ef::EmitterParameter[SLOW_MAX_EMITTER];
- mParticleParamSave[i] = //
+ mpParticleParamSave[i] = //
new nw4r::ef::ParticleParameter[SLOW_MAX_PARTICLE];
}
}
@@ -226,20 +226,20 @@ void RPSysEffectCreator::update() {
const nw4r::ut::List *pListEmitter, *pListParticle;
const nw4r::ef::EmitterParameter* pLoadEmitter =
- mEmitterParamSave[mBackSaveBuffer == ESaveBuffer_1st
- ? ESaveBuffer_2nd
- : ESaveBuffer_1st];
-
- const nw4r::ef::ParticleParameter* pLoadParticle =
- mParticleParamSave[mBackSaveBuffer == ESaveBuffer_1st
+ mpEmitterParamSave[mBackSaveBuffer == ESaveBuffer_1st
? ESaveBuffer_2nd
: ESaveBuffer_1st];
+ const nw4r::ef::ParticleParameter* pLoadParticle =
+ mpParticleParamSave[mBackSaveBuffer == ESaveBuffer_1st
+ ? ESaveBuffer_2nd
+ : ESaveBuffer_1st];
+
nw4r::ef::EmitterParameter* pSaveEmitter =
- mEmitterParamSave[mBackSaveBuffer];
+ mpEmitterParamSave[mBackSaveBuffer];
nw4r::ef::ParticleParameter* pSaveParticle =
- mParticleParamSave[mBackSaveBuffer];
+ mpParticleParamSave[mBackSaveBuffer];
pListEmitter = &mpMemoryManager->mEmitterOM->mLeasedList;
pListParticle = &mpMemoryManager->mParticleOM->mLeasedList;
diff --git a/src/Pack/RPKernel/RPSysEffectMgr.cpp b/src/Pack/RPKernel/RPSysEffectMgr.cpp
index b035ccf61..cc0bb8426 100644
--- a/src/Pack/RPKernel/RPSysEffectMgr.cpp
+++ b/src/Pack/RPKernel/RPSysEffectMgr.cpp
@@ -128,15 +128,15 @@ void RPSysEffectMgr::setCaptureEfb(void* pTexture, const EfbTexData& rData) {
/**
* @brief Draws the specified set of effects
*
- * @param rDrawInfo Graphics configuration
+ * @param rViewMtx Graphics configuration
* @param drawGroup Effect draw group
* @param drawScene Effect draw scene
*/
-void RPSysEffectMgr::draw(const nw4r::ef::DrawInfo& rDrawInfo, u32 drawGroup,
+void RPSysEffectMgr::draw(const nw4r::math::MTX34& rViewMtx, u32 drawGroup,
u32 drawScene) {
- nw4r::ef::DrawInfo sceneDrawInfo;
- sceneDrawInfo.SetViewMtx(*rDrawInfo.GetViewMtx());
+ nw4r::ef::DrawInfo drawInfo;
+ drawInfo.SetViewMtx(rViewMtx);
RPGrpScreen* pScreen = RPGrpRenderer::GetCurrentScreen();
RPGrpView* pView = RPGrpRenderer::GetCurrentView();
@@ -151,7 +151,7 @@ void RPSysEffectMgr::draw(const nw4r::ef::DrawInfo& rDrawInfo, u32 drawGroup,
C_MTXLightOrtho(proj, cy, -cy, -cx, cx, 0.5f, -0.5f, 0.5f, 0.5f);
}
- sceneDrawInfo.SetProjMtx(proj);
+ drawInfo.SetProjMtx(proj);
if (drawGroup < EDrawGroup_16) {
for (int i = 0; i < EDrawScene_Max; i++) {
@@ -159,7 +159,7 @@ void RPSysEffectMgr::draw(const nw4r::ef::DrawInfo& rDrawInfo, u32 drawGroup,
continue;
}
- mpEffectCreators[i]->draw(sceneDrawInfo, drawGroup, drawScene);
+ mpEffectCreators[i]->draw(drawInfo, drawGroup, drawScene);
}
}
}
From b023793ae537629360890bb6078db1985049b511 Mon Sep 17 00:00:00 2001
From: kiwi515 <49212064+kiwi515@users.noreply.github.com>
Date: Sat, 12 Sep 2026 16:27:57 -0400
Subject: [PATCH 2/4] docs
---
include/Pack/RPGraphics/RPGrpView.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/Pack/RPGraphics/RPGrpView.h b/include/Pack/RPGraphics/RPGrpView.h
index 59f5ec76b..b6029061b 100644
--- a/include/Pack/RPGraphics/RPGrpView.h
+++ b/include/Pack/RPGraphics/RPGrpView.h
@@ -162,17 +162,17 @@ class RPGrpView {
* @brief Renderer view flags
*/
enum {
- //! View will be updated and rendered
+ //! Update this view
EFlag_SysCalc = 1 << 0,
-
//! Update color when clearing the framebuffer
EFlag_FillBufferColor = 1 << 1,
//! Update alpha when clearing the framebuffer
EFlag_FillBufferAlpha = 1 << 2,
//! Update depth when clearing the framebuffer
EFlag_FillBufferTexture = 1 << 3,
-
+ //! Render this view
EFlag_SysDraw = 1 << 4,
+
EFlag_9 = 1 << 9,
};
From 65303647f351c641773f0bcad774e906df0b576c Mon Sep 17 00:00:00 2001
From: kiwi515 <49212064+kiwi515@users.noreply.github.com>
Date: Sat, 12 Sep 2026 16:29:20 -0400
Subject: [PATCH 3/4] Update symbols.txt
---
config/RSPE01_01/symbols.txt | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/config/RSPE01_01/symbols.txt b/config/RSPE01_01/symbols.txt
index 5fe01cc90..3cc889e01 100644
--- a/config/RSPE01_01/symbols.txt
+++ b/config/RSPE01_01/symbols.txt
@@ -7996,17 +7996,17 @@ Draw__17RPGrpViewRender2DFv = .text:0x801B1624; // type:function size:0x48
PrepareDraw__17RPGrpViewRender2DFv = .text:0x801B166C; // type:function size:0x4
Configure__17RPGrpViewRender2DFv = .text:0x801B1670; // type:function size:0x4
__ct__17RPGrpViewRender2DFUc = .text:0x801B1674; // type:function size:0x44
-__dt__17RPGrpViewRender2DFv = .text:0x801B16B8; // type:function size:0x40
-GetType__17RPGrpViewRender2DCFv = .text:0x801B16F8; // type:function size:0x8
+__dt__17RPGrpViewRender2DFv = .text:0x801B16B8; // type:function size:0x40 scope:weak
+GetType__17RPGrpViewRender2DCFv = .text:0x801B16F8; // type:function size:0x8 scope:weak
AttachCamera__17RPGrpViewRender3DFP11RPGrpCamera = .text:0x801B1700; // type:function size:0x10
PrepareDrawGX__17RPGrpViewRender3DFv = .text:0x801B1710; // type:function size:0x30
Draw__17RPGrpViewRender3DFv = .text:0x801B1740; // type:function size:0x38
PrepareDraw__17RPGrpViewRender3DFv = .text:0x801B1778; // type:function size:0xD8
Calc__17RPGrpViewRender3DFv = .text:0x801B1850; // type:function size:0x6C
-GetCamera__17RPGrpViewRender3DCFv = .text:0x801B18BC; // type:function size:0x8
+GetCamera__17RPGrpViewRender3DCFv = .text:0x801B18BC; // type:function size:0x8 scope:weak
__ct__17RPGrpViewRender3DFUc = .text:0x801B18C4; // type:function size:0x4C
-__dt__17RPGrpViewRender3DFv = .text:0x801B1910; // type:function size:0x40
-GetType__17RPGrpViewRender3DCFv = .text:0x801B1950; // type:function size:0x8
+__dt__17RPGrpViewRender3DFv = .text:0x801B1910; // type:function size:0x40 scope:weak
+GetType__17RPGrpViewRender3DCFv = .text:0x801B1950; // type:function size:0x8 scope:weak
fn_801B1958 = .text:0x801B1958; // type:function size:0x98
fn_801B19F0 = .text:0x801B19F0; // type:function size:0x24
fn_801B1A14 = .text:0x801B1A14; // type:function size:0x80
@@ -18676,8 +18676,8 @@ lbl_803BA5B0 = .data:0x803BA5B0; // type:object size:0xD data:string
lbl_803BA5C0 = .data:0x803BA5C0; // type:object size:0x2C
lbl_803BA5EC = .data:0x803BA5EC; // type:object size:0xC
lbl_803BA5F8 = .data:0x803BA5F8; // type:object size:0x10
-__vt__17RPGrpViewRender2D = .data:0x803BA608; // type:object size:0x30
-__vt__17RPGrpViewRender3D = .data:0x803BA638; // type:object size:0x30
+__vt__17RPGrpViewRender2D = .data:0x803BA608; // type:object size:0x2C
+__vt__17RPGrpViewRender3D = .data:0x803BA638; // type:object size:0x2C
lbl_803BA668 = .data:0x803BA668; // type:object size:0x10
lbl_803BA678 = .data:0x803BA678; // type:object size:0x20
lbl_803BA698 = .data:0x803BA698; // type:object size:0x28
From 680ce5a4d3b22a3cd25ec932eff68ed955545689 Mon Sep 17 00:00:00 2001
From: kiwi515 <49212064+kiwi515@users.noreply.github.com>
Date: Sat, 12 Sep 2026 16:31:41 -0400
Subject: [PATCH 4/4] Update eggCapTexture.h
---
include/egg/gfxe/eggCapTexture.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/egg/gfxe/eggCapTexture.h b/include/egg/gfxe/eggCapTexture.h
index 78a1199ae..bfc3c5278 100644
--- a/include/egg/gfxe/eggCapTexture.h
+++ b/include/egg/gfxe/eggCapTexture.h
@@ -19,12 +19,12 @@ class CapTexture : public CpuTexture {
void capture(u16 x, u16 y, bool mipmap = false, int format = -1);
- void setLoadMap(GXTexMapID loadMap) {
- mLoadMap = loadMap;
- }
GXTexMapID getLoadMap() const {
return mLoadMap;
}
+ void setLoadMap(GXTexMapID loadMap) {
+ mLoadMap = loadMap;
+ }
void setClearColor(const GXColor& rColor) {
mClearColor = rColor;