From 8f389e246c2f7d7e5af2f66a8250df497c09e812 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Tue, 26 Jul 2022 01:08:14 -0400 Subject: [PATCH] Some WIP implementations --- Runtime/Camera/CCameraFilter.cpp | 14 ++- Runtime/Graphics/CCubeRenderer.cpp | 191 ++++++++++++++++++++++++++++- Runtime/Graphics/CCubeRenderer.hpp | 3 +- Runtime/Graphics/CGX.hpp | 27 +++- Runtime/World/CMorphBallShadow.cpp | 2 +- 5 files changed, 224 insertions(+), 13 deletions(-) diff --git a/Runtime/Camera/CCameraFilter.cpp b/Runtime/Camera/CCameraFilter.cpp index aa587bfbc..b49a832dd 100644 --- a/Runtime/Camera/CCameraFilter.cpp +++ b/Runtime/Camera/CCameraFilter.cpp @@ -272,6 +272,7 @@ void CCameraFilterPass::DrawRandomStatic(const zeus::CColor& color, float alpha, } void CCameraFilterPass::DrawScanLines(const zeus::CColor& color, bool even) { + SCOPED_GRAPHICS_DEBUG_GROUP("CCameraFilterPass::DrawScanLines", zeus::skBlue); const auto [lt, rb] = g_Renderer->SetViewportOrtho(true, -4096.f, 4096.f); g_Renderer->SetDepthReadWrite(false, false); g_Renderer->SetModelMatrix({}); @@ -282,7 +283,18 @@ void CCameraFilterPass::DrawScanLines(const zeus::CColor& color, bool even) { } void CCameraFilterPass::DrawWideScreen(const zeus::CColor& color, CTexture* tex, float lod) { - // TODO + SCOPED_GRAPHICS_DEBUG_GROUP("CCameraFilterPass::DrawWideScreen", zeus::skBlue); + // const auto vp = g_Renderer->SetViewportOrtho(true, -4096.f, 4096.f); + // float f = -((vp.second.x() - vp.first.x()) * 0.0625f * 9.f - (vp.second.y() - vp.first.y())) * 0.5f; + // g_Renderer->SetDepthReadWrite(false, false); + // g_Renderer->SetModelMatrix({}); + // if (tex != nullptr) { + // tex->Load(GX::TEXMAP0, EClampMode::Repeat); + // } + // CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc); + // CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru); + // CGraphics::StreamBegin(GX::TRIANGLESTRIP); + // float x = rand() % 4000; } void CCameraBlurPass::Draw(bool clearDepth) { diff --git a/Runtime/Graphics/CCubeRenderer.cpp b/Runtime/Graphics/CCubeRenderer.cpp index f8fd7c220..8cb58c6e4 100644 --- a/Runtime/Graphics/CCubeRenderer.cpp +++ b/Runtime/Graphics/CCubeRenderer.cpp @@ -1235,19 +1235,135 @@ CCubeRenderer::FindStaticGeometry(const std::vector* geom } void CCubeRenderer::FindOverlappingWorldModels(std::vector& modelBits, const zeus::CAABox& aabb) const { - // TODO + u32 bitmapWords = 0; + for (const CAreaListItem& item : x1c_areaListItems) { + if (item.x4_octTree != nullptr) { + bitmapWords += item.x4_octTree->x14_bitmapWordCount; + } + } + + if (bitmapWords == 0u) { + modelBits.clear(); + return; + } + + modelBits.clear(); + modelBits.resize(bitmapWords); + + u32 curWord = 0; + for (const CAreaListItem& item : x1c_areaListItems) { + if (item.x4_octTree == nullptr) { + continue; + } + + item.x4_octTree->FindOverlappingModels(modelBits.data() + curWord, aabb); + + u32 wordModel = 0; + for (u32 i = 0; i < item.x4_octTree->x14_bitmapWordCount; ++i, wordModel += 32) { + u32& word = modelBits[curWord + i]; + if (word == 0) { + continue; + } + for (u32 j = 0; j < 32; ++j) { + if (((1U << j) & word) != 0) { + const zeus::CAABox& modelAABB = (*item.x10_models)[wordModel + j]->GetBounds(); + if (!modelAABB.intersects(aabb)) { + word &= ~(1U << j); + } + } + } + } + + curWord += item.x4_octTree->x14_bitmapWordCount; + } } s32 CCubeRenderer::DrawOverlappingWorldModelIDs(s32 alphaVal, const std::vector& modelBits, const zeus::CAABox& aabb) { + SCOPED_GRAPHICS_DEBUG_GROUP("CCubeRenderer::DrawOverlappingWorldModelIDs", zeus::skGrey); SetupRendererStates(true); - // TODO - return 0; + + constexpr CModelFlags flags{0, 0, 3, zeus::skWhite}; + + u32 curWord = 0; + for (const CAreaListItem& item : x1c_areaListItems) { + if (item.x4_octTree == nullptr) { + continue; + } + + u32 wordModel = 0; + for (u32 i = 0; i < item.x4_octTree->x14_bitmapWordCount; ++i, wordModel += 32) { + const u32& word = modelBits[curWord + i]; + if (word == 0) { + continue; + } + for (u32 j = 0; j < 32; ++j) { + if (((1U << j) & word) != 0) { + if (alphaVal > 255) { + SetupCGraphicsState(); + return alphaVal; + } + + auto& model = *(*item.x10_models)[wordModel + j]; + GXSetDstAlpha(true, alphaVal); + CCubeMaterial::KillCachedViewDepState(); + model.SetArraysCurrent(); + for (const auto* surf = model.GetFirstUnsortedSurface(); surf != nullptr; surf = surf->GetNextSurface()) { + if (surf->GetBounds().intersects(aabb)) { + model.DrawSurface(*surf, flags); + } + } + alphaVal += 4; + } + } + } + + curWord += item.x4_octTree->x14_bitmapWordCount; + } + + SetupCGraphicsState(); + return alphaVal; } void CCubeRenderer::DrawOverlappingWorldModelShadows(s32 alphaVal, const std::vector& modelBits, - const zeus::CAABox& aabb, float alpha) { - // TODO + const zeus::CAABox& aabb) { + SCOPED_GRAPHICS_DEBUG_GROUP("CBooRenderer::DrawOverlappingWorldModelShadows", zeus::skGrey); + + u32 curWord = 0; + for (const CAreaListItem& item : x1c_areaListItems) { + if (item.x4_octTree == nullptr) { + continue; + } + + u32 wordModel = 0; + for (u32 i = 0; i < item.x4_octTree->x14_bitmapWordCount; ++i, wordModel += 32) { + const u32& word = modelBits[curWord + i]; + if (word == 0) { + continue; + } + for (u32 j = 0; j < 32; ++j) { + if (((1U << j) & word) != 0) { + if (alphaVal > 255) { + return; + } + + auto& model = *(*item.x10_models)[wordModel + j]; + CGX::SetTevKColor(GX::KCOLOR0, zeus::CColor{0.f, static_cast(alphaVal) / 255.f}); + model.SetArraysCurrent(); + for (const auto* surf = model.GetFirstUnsortedSurface(); surf != nullptr; surf = surf->GetNextSurface()) { + if (surf->GetBounds().intersects(aabb)) { + const auto& material = model.GetMaterialByIndex(surf->GetMaterialIndex()); + CGX::SetVtxDescv_Compressed(material.GetVertexDesc()); + CGX::CallDisplayList(surf->GetDisplayList(), surf->GetDisplayListSize()); + } + } + alphaVal += 4; + } + } + } + + curWord += item.x4_octTree->x14_bitmapWordCount; + } } void CCubeRenderer::SetupCGraphicsState() { @@ -1306,7 +1422,70 @@ void CCubeRenderer::DoThermalModelDraw(CCubeModel& model, const zeus::CColor& mu } void CCubeRenderer::ReallyDrawSpaceWarp(const zeus::CVector3f& pt, float strength) { - // TODO + return; // TODO + + float vpLeft = static_cast(CGraphics::GetViewportLeft()); + float vpTop = static_cast(CGraphics::GetViewportTop()); + float vpHalfWidth = static_cast(CGraphics::GetViewportWidth() / 2); + float vpHalfHeight = static_cast(CGraphics::GetViewportHeight() / 2); + float local_100 = vpLeft + vpHalfWidth * pt.x() + vpHalfWidth; + float local_fc = vpTop + vpHalfHeight * -pt.y() + vpHalfHeight; + zeus::CVector2i CStack264{static_cast(local_100) & ~3, static_cast(local_fc) & ~3}; + auto v2right = CStack264 - zeus::CVector2i{96, 96}; + auto v2left = CStack264 + zeus::CVector2i{96, 96}; + zeus::CVector2f uv1min{0.f, 0.f}; + zeus::CVector2f uv1max{1.f, 1.f}; + + s32 aleft = CGraphics::GetViewportLeft() & ~3; + s32 atop = CGraphics::GetViewportTop() & ~3; + s32 aright = (CGraphics::GetViewportLeft() + CGraphics::GetViewportWidth() + 3) & ~3; + s32 abottom = (CGraphics::GetViewportTop() + CGraphics::GetViewportHeight() + 3) & ~3; + if (v2right.x < aleft) { + uv1min.x() = static_cast(aleft - v2right.x) * 0.005208333f; + v2right.x = aleft; + } + if (v2right.y < atop) { + uv1min.y() = static_cast(atop - v2right.x) * 0.005208333f; + v2right.y = atop; + } + if (v2left.x > aright) { + uv1max.x() = 1.f - static_cast(v2left.x - aright) * 0.005208333f; + v2left.x = aright; + } + if (v2left.y > abottom) { + uv1max.y() = 1.f - static_cast(v2left.y - abottom) * 0.005208333f; + v2left.y = abottom; + } + const auto v2sub = v2left - v2right; + if (v2sub.x > 0 && v2sub.y > 0) { + GX::FogType fogType; + float fogStartZ; + float fogEndZ; + float fogNearZ; + float fogFarZ; + GXColor fogColor; + CGX::GetFog(&fogType, &fogStartZ, &fogEndZ, &fogNearZ, &fogFarZ, &fogColor); + CGX::SetFog(GX::FOG_NONE, fogStartZ, fogEndZ, fogNearZ, fogFarZ, fogColor); + // GXSetTexCopySrc(v2right.x, v2right.y, v2sub.x, v2sub.y); + // GXSetTexCopyDst(v2sub.x, v2sub.y, GX::TF_RGBA8, false); + // GXCopyTex(sSpareTextureData, false); + // GXPixModeSync(); + CGraphics::ResolveSpareTexture( + SViewport{ + .x0_left = static_cast(v2right.x), + .x4_top = static_cast(v2right.y), + .x8_width = static_cast(v2sub.x), + .xc_height = static_cast(v2sub.y), + }, + 1, GX::TF_RGBA8); + CGraphics::LoadDolphinSpareTexture(1, GX::TF_RGBA8, GX::TEXMAP7); + x150_reflectionTex.Load(GX::TEXMAP1, EClampMode::Clamp); + CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_TEXC); + CGX::SetTevColorOp(GX::TEVSTAGE0, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV); + CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX3x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY); + CGX::SetTexCoordGen(GX::TEXCOORD1, GX::TG_MTX3x4, GX::TG_TEX1, GX::IDENTITY, false, GX::PTIDENTITY); + CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP7, GX::COLOR_NULL); + } } void CCubeRenderer::ReallyRenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb, const CModel* model, diff --git a/Runtime/Graphics/CCubeRenderer.hpp b/Runtime/Graphics/CCubeRenderer.hpp index d805453fc..7c0a96a97 100644 --- a/Runtime/Graphics/CCubeRenderer.hpp +++ b/Runtime/Graphics/CCubeRenderer.hpp @@ -212,8 +212,7 @@ public: std::list::iterator FindStaticGeometry(const std::vector* geometry); void FindOverlappingWorldModels(std::vector& modelBits, const zeus::CAABox& aabb) const; s32 DrawOverlappingWorldModelIDs(s32 alphaVal, const std::vector& modelBits, const zeus::CAABox& aabb); - void DrawOverlappingWorldModelShadows(s32 alphaVal, const std::vector& modelBits, const zeus::CAABox& aabb, - float alpha); + void DrawOverlappingWorldModelShadows(s32 alphaVal, const std::vector& modelBits, const zeus::CAABox& aabb); void RenderBucketItems(const CAreaListItem* lights); void DrawRenderBucketsDebug() {} diff --git a/Runtime/Graphics/CGX.hpp b/Runtime/Graphics/CGX.hpp index bc5e3bfe8..ff52bdb10 100644 --- a/Runtime/Graphics/CGX.hpp +++ b/Runtime/Graphics/CGX.hpp @@ -3,7 +3,6 @@ #include "Graphics/GX.hpp" #include "RetroTypes.hpp" -#include #include namespace metaforce::CGX { @@ -338,8 +337,8 @@ static inline void SetTevIndirect(GX::TevStageID stageId, GX::IndTexStageID indS GXSetTevIndirect(stageId, indStage, fmt, biasSel, mtxSel, wrapS, wrapT, addPrev, indLod, alphaSel); } -static inline void SetTevIndWarp(GX::TevStageID stageId, GX::IndTexStageID indStage, GXBool signedOffset, GXBool replaceMode, - GX::IndTexMtxID mtxSel) noexcept { +static inline void SetTevIndWarp(GX::TevStageID stageId, GX::IndTexStageID indStage, GXBool signedOffset, + GXBool replaceMode, GX::IndTexMtxID mtxSel) noexcept { // TODO GXSetTevIndWarp(stageId, indStage, signedOffset, replaceMode, mtxSel); } @@ -436,4 +435,26 @@ static inline void SetZMode(GXBool compareEnable, GX::Compare func, GXBool updat GXSetZMode(compareEnable, func, updateEnable); } } + +static inline void GetFog(GX::FogType* fogType, float* fogStartZ, float* fogEndZ, float* fogNearZ, float* fogFarZ, + GXColor* fogColor) { + if (fogType != nullptr) { + *fogType = sGXState.x53_fogType; + } + if (fogStartZ != nullptr) { + *fogStartZ = sGXState.x24c_fogStartZ; + } + if (fogEndZ != nullptr) { + *fogEndZ = sGXState.x250_fogEndZ; + } + if (fogNearZ != nullptr) { + *fogNearZ = sGXState.x254_fogNearZ; + } + if (fogFarZ != nullptr) { + *fogFarZ = sGXState.x258_fogFarZ; + } + if (fogColor != nullptr) { + *fogColor = sGXState.x25c_fogColor; + } +} } // namespace metaforce::CGX diff --git a/Runtime/World/CMorphBallShadow.cpp b/Runtime/World/CMorphBallShadow.cpp index e5a13c920..ecffe6a7d 100644 --- a/Runtime/World/CMorphBallShadow.cpp +++ b/Runtime/World/CMorphBallShadow.cpp @@ -136,7 +136,7 @@ void CMorphBallShadow::Render(const CStateManager& mgr, float alpha) { } CGraphics::SetModelMatrix(zeus::CTransform()); - g_Renderer->DrawOverlappingWorldModelShadows(alphaVal, x30_worldModelBits, xb8_shadowVolume, alpha); + g_Renderer->DrawOverlappingWorldModelShadows(alphaVal, x30_worldModelBits, xb8_shadowVolume); } } // namespace metaforce