Transition all Textured/ColoredQuad usages

- Upload textures using staging buffer
- Fixes SetOrtho logic
- More work on thermal visor rendering (still WIP)
- Rework Dawn backend initialization
- Support MoltenVK on Metal
- Various fixes & cleanup
This commit is contained in:
Luke Street 2022-05-23 20:26:35 -04:00
parent 36a7bfc464
commit f80813b9cc
65 changed files with 857 additions and 687 deletions

View File

@ -1450,17 +1450,17 @@ void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, flo
if (IsInMapperState(EAutoMapperState::MapScreen)) { if (IsInMapperState(EAutoMapperState::MapScreen)) {
CAssetId wldMlvl = x24_world->IGetWorldAssetId(); CAssetId wldMlvl = x24_world->IGetWorldAssetId();
const CMapWorld* mw = x24_world->IGetMapWorld(); const CMapWorld* mw = x24_world->IGetMapWorld();
std::vector<CTexturedQuadFilter>& hintBeaconFilters = m_hintBeaconFilters; // std::vector<CTexturedQuadFilter>& hintBeaconFilters = m_hintBeaconFilters;
if (hintBeaconFilters.size() < x1f8_hintLocations.size()) { // if (hintBeaconFilters.size() < x1f8_hintLocations.size()) {
hintBeaconFilters.reserve(x1f8_hintLocations.size()); // hintBeaconFilters.reserve(x1f8_hintLocations.size());
for (u32 i = hintBeaconFilters.size(); i < x1f8_hintLocations.size(); ++i) // for (u32 i = hintBeaconFilters.size(); i < x1f8_hintLocations.size(); ++i)
hintBeaconFilters.emplace_back(EFilterType::Add, x3c_hintBeacon); // hintBeaconFilters.emplace_back(EFilterType::Add, x3c_hintBeacon);
} // }
auto locIt = x1f8_hintLocations.cbegin(); auto locIt = x1f8_hintLocations.cbegin();
auto filterIt = hintBeaconFilters.begin(); // auto filterIt = hintBeaconFilters.begin();
for (; locIt != x1f8_hintLocations.cend(); ++locIt, ++filterIt) { for (; locIt != x1f8_hintLocations.cend(); ++locIt/*, ++filterIt*/) {
const SAutoMapperHintLocation& loc = *locIt; const SAutoMapperHintLocation& loc = *locIt;
CTexturedQuadFilter& filter = *filterIt; // CTexturedQuadFilter& filter = *filterIt;
if (loc.x8_worldId != wldMlvl) if (loc.x8_worldId != wldMlvl)
continue; continue;
const CMapArea* mapa = mw->GetMapArea(loc.xc_areaId); const CMapArea* mapa = mw->GetMapArea(loc.xc_areaId);
@ -1475,12 +1475,12 @@ void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, flo
beaconAlpha = loc.x4_beaconAlpha; beaconAlpha = loc.x4_beaconAlpha;
} }
if (beaconAlpha > 0.f) { if (beaconAlpha > 0.f) {
constexpr std::array<CTexturedQuadFilter::Vert, 4> verts{{ // constexpr std::array<CTexturedQuadFilter::Vert, 4> verts{{
{{-4.f, -8.f, 8.f}, {0.f, 1.f}}, // {{-4.f, -8.f, 8.f}, {0.f, 1.f}},
{{-4.f, -8.f, 0.f}, {0.f, 0.f}}, // {{-4.f, -8.f, 0.f}, {0.f, 0.f}},
{{4.f, -8.f, 8.f}, {1.f, 1.f}}, // {{4.f, -8.f, 8.f}, {1.f, 1.f}},
{{4.f, -8.f, 0.f}, {1.f, 0.f}}, // {{4.f, -8.f, 0.f}, {1.f, 0.f}},
}}; // }};
float colorAlpha = beaconAlpha; float colorAlpha = beaconAlpha;
if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) { if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) {
} else { } else {
@ -1489,7 +1489,8 @@ void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, flo
colorAlpha *= mapAlpha; colorAlpha *= mapAlpha;
zeus::CColor color = zeus::skWhite; zeus::CColor color = zeus::skWhite;
color.a() = colorAlpha; color.a() = colorAlpha;
filter.drawVerts(color, verts); // TODO
// filter.drawVerts(color, verts);
} }
} }
} }

View File

@ -133,7 +133,6 @@ private:
bool m_frmeInitialized = false; bool m_frmeInitialized = false;
TLockedToken<CModel> x30_miniMapSamus; TLockedToken<CModel> x30_miniMapSamus;
TLockedToken<CTexture> x3c_hintBeacon; TLockedToken<CTexture> x3c_hintBeacon;
std::vector<CTexturedQuadFilter> m_hintBeaconFilters;
rstl::reserved_vector<TLockedToken<CTexture>, 5> x48_mapIcons; rstl::reserved_vector<TLockedToken<CTexture>, 5> x48_mapIcons;
CAssetId x74_areaHintDescId; CAssetId x74_areaHintDescId;
TLockedToken<CStringTable> x78_areaHintDesc; TLockedToken<CStringTable> x78_areaHintDesc;

View File

@ -167,16 +167,16 @@ void CMappableObject::Draw(int curArea, const CMapWorldInfo& mwInfo, float alpha
iconColor.a() *= alpha; iconColor.a() *= alpha;
TLockedToken<CTexture> tex = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), iconRes}); TLockedToken<CTexture> tex = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), iconRes});
if (!m_texQuadFilter || m_texQuadFilter->GetTex().GetObj() != tex.GetObj()) { // if (!m_texQuadFilter || m_texQuadFilter->GetTex().GetObj() != tex.GetObj()) {
//m_texQuadFilter.emplace(EFilterType::Add, tex, CTexturedQuadFilter::ZTest::GEqual); //m_texQuadFilter.emplace(EFilterType::Add, tex, CTexturedQuadFilter::ZTest::GEqual);
} // }
constexpr std::array<CTexturedQuadFilter::Vert, 4> verts{{ // constexpr std::array<CTexturedQuadFilter::Vert, 4> verts{{
{{-2.6f, 0.f, 2.6f}, {0.f, 1.f}}, // {{-2.6f, 0.f, 2.6f}, {0.f, 1.f}},
{{-2.6f, 0.f, -2.6f}, {0.f, 0.f}}, // {{-2.6f, 0.f, -2.6f}, {0.f, 0.f}},
{{2.6f, 0.f, 2.6f}, {1.f, 1.f}}, // {{2.6f, 0.f, 2.6f}, {1.f, 1.f}},
{{2.6f, 0.f, -2.6f}, {1.f, 0.f}}, // {{2.6f, 0.f, -2.6f}, {1.f, 0.f}},
}}; // }};
//m_texQuadFilter->drawVerts(iconColor, verts); //m_texQuadFilter->drawVerts(iconColor, verts);
} }
} }

View File

@ -7,7 +7,6 @@
#include "Runtime/GameGlobalObjects.hpp" #include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Graphics/CLineRenderer.hpp" #include "Runtime/Graphics/CLineRenderer.hpp"
#include "Runtime/Graphics/Shaders/CMapSurfaceShader.hpp" #include "Runtime/Graphics/Shaders/CMapSurfaceShader.hpp"
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp"
#include "Runtime/RetroTypes.hpp" #include "Runtime/RetroTypes.hpp"
#include <zeus/CAABox.hpp> #include <zeus/CAABox.hpp>
@ -67,7 +66,6 @@ private:
, m_outline(CLineRenderer::EPrimitiveMode::LineLoop, 5, {}, false, false, true) {} , m_outline(CLineRenderer::EPrimitiveMode::LineLoop, 5, {}, false, false, true) {}
}; };
std::optional<DoorSurface> m_doorSurface; std::optional<DoorSurface> m_doorSurface;
std::optional<CTexturedQuadFilter> m_texQuadFilter;
zeus::CTransform AdjustTransformForType() const; zeus::CTransform AdjustTransformForType() const;
std::pair<zeus::CColor, zeus::CColor> GetDoorColors(int idx, const CMapWorldInfo& mwInfo, float alpha) const; std::pair<zeus::CColor, zeus::CColor> GetDoorColors(int idx, const CMapWorldInfo& mwInfo, float alpha) const;

View File

@ -623,7 +623,7 @@ void CStateManager::DrawE3DeathEffect() {
const float whiteAmt = zeus::clamp(0.f, 1.f - player.x9f4_deathTime / (0.05f * 6.f), 1.f); const float whiteAmt = zeus::clamp(0.f, 1.f - player.x9f4_deathTime / (0.05f * 6.f), 1.f);
zeus::CColor color = zeus::skWhite; zeus::CColor color = zeus::skWhite;
color.a() = whiteAmt; color.a() = whiteAmt;
m_deathWhiteout.draw(color); CCameraFilterPass::DrawFilter(EFilterType::Add, EFilterShape::Fullscreen, color, nullptr, 1.f);
} }
void CStateManager::DrawAdditionalFilters() { void CStateManager::DrawAdditionalFilters() {
@ -633,7 +633,7 @@ void CStateManager::DrawAdditionalFilters() {
zeus::CColor color = zeus::skWhite; zeus::CColor color = zeus::skWhite;
color.a() = 1.f - xf0c_escapeTimer; color.a() = 1.f - xf0c_escapeTimer;
m_escapeWhiteout.draw(color); CCameraFilterPass::DrawFilter(EFilterType::Add, EFilterShape::Fullscreen, color, nullptr, 1.f);
} }
zeus::CFrustum CStateManager::SetupDrawFrustum(const SViewport& vp) const { zeus::CFrustum CStateManager::SetupDrawFrustum(const SViewport& vp) const {
@ -674,32 +674,13 @@ zeus::CFrustum CStateManager::SetupViewForDraw(const SViewport& vp) const {
proj.setPersp(zeus::SProjPersp{fov, width / height, cam->GetNearClipDistance(), cam->GetFarClipDistance()}); proj.setPersp(zeus::SProjPersp{fov, width / height, cam->GetNearClipDistance(), cam->GetFarClipDistance()});
frustum.updatePlanes(camXf, proj); frustum.updatePlanes(camXf, proj);
g_Renderer->SetClippingPlanes(frustum); g_Renderer->SetClippingPlanes(frustum);
// g_Renderer->PrimColor(zeus::skWhite); g_Renderer->PrimColor(zeus::skWhite);
CGraphics::SetModelMatrix(zeus::CTransform()); CGraphics::SetModelMatrix(zeus::CTransform());
x87c_fluidPlaneManager->StartFrame(false); x87c_fluidPlaneManager->StartFrame(false);
g_Renderer->SetDebugOption(IRenderer::EDebugOption::PVSState, int(EPVSVisSetState::NodeFound)); g_Renderer->SetDebugOption(IRenderer::EDebugOption::PVSState, int(EPVSVisSetState::NodeFound));
return frustum; return frustum;
} }
zeus::CFrustum CStateManager::SetupViewForCubeFaceDraw(const zeus::CVector3f& pos, int face) const {
const zeus::CTransform mainCamXf = x870_cameraManager->GetCurrentCameraTransform(*this);
const zeus::CTransform camXf = zeus::CTransform(mainCamXf.basis * CGraphics::skCubeBasisMats[face], pos);
g_Renderer->SetWorldViewpoint(camXf);
CCubeModel::SetNewPlayerPositionAndTime(x84c_player->GetTranslation(), CStopwatch::GetGlobalTimerObj());
constexpr float width = CUBEMAP_RES;
g_Renderer->SetViewport(0, 0, width, width);
CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR);
constexpr float fov = zeus::degToRad(90.f);
g_Renderer->SetPerspective(zeus::radToDeg(fov), width, width, 0.2f, 750.f);
zeus::CFrustum frustum;
zeus::CProjection proj;
proj.setPersp(zeus::SProjPersp{fov, 1.f, 0.2f, 750.f});
frustum.updatePlanes(camXf, proj);
g_Renderer->SetClippingPlanes(frustum);
CGraphics::SetModelMatrix(zeus::CTransform());
return frustum;
}
void CStateManager::ResetViewAfterDraw(const SViewport& backupViewport, void CStateManager::ResetViewAfterDraw(const SViewport& backupViewport,
const zeus::CTransform& backupViewMatrix) const { const zeus::CTransform& backupViewMatrix) const {
g_Renderer->SetViewport(backupViewport.x0_left, backupViewport.x4_top, backupViewport.x8_width, g_Renderer->SetViewport(backupViewport.x0_left, backupViewport.x4_top, backupViewport.x8_width,
@ -725,8 +706,6 @@ void CStateManager::DrawWorld() {
x850_world->TouchSky(); x850_world->TouchSky();
DrawWorldCubeFaces();
const zeus::CFrustum frustum = SetupViewForDraw(CGraphics::g_Viewport); const zeus::CFrustum frustum = SetupViewForDraw(CGraphics::g_Viewport);
const zeus::CTransform backupViewMatrix = CGraphics::g_ViewMatrix; const zeus::CTransform backupViewMatrix = CGraphics::g_ViewMatrix;
@ -983,120 +962,6 @@ void CStateManager::DrawWorld() {
DrawAdditionalFilters(); DrawAdditionalFilters();
} }
void CStateManager::DrawActorCubeFaces(CActor& actor, int& cubeInst) const {
// if (!actor.m_reflectionCube ||
// (!TCastToPtr<CPlayer>(actor) && (!actor.GetActive() || !actor.IsDrawEnabled() || actor.xe4_30_outOfFrustum)))
// return;
//
// const TAreaId visAreaId = actor.GetAreaIdAlways();
// const SViewport backupVp = g_Viewport;
//
// int areaCount = 0;
// std::array<const CGameArea*, 10> areaArr;
// for (const CGameArea& area : *x850_world) {
// if (areaCount == 10) {
// break;
// }
// auto occState = CGameArea::EOcclusionState::Occluded;
// if (area.IsPostConstructed()) {
// occState = area.GetOcclusionState();
// }
// if (occState == CGameArea::EOcclusionState::Visible) {
// areaArr[areaCount++] = &area;
// }
// }
//
// for (int f = 0; f < 6; ++f) {
// SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CStateManager::DrawActorCubeFaces [{}] {} {} {}"), f,
// actor.GetUniqueId(), actor.GetEditorId(), actor.GetName())
// .c_str(),
// zeus::skOrange);
// CGraphics::g_BooMainCommandQueue->setRenderTarget(actor.m_reflectionCube, f);
// SetupViewForCubeFaceDraw(actor.GetRenderBounds().center(), f);
// CGraphics::g_BooMainCommandQueue->clearTarget();
//
// std::sort(areaArr.begin(), areaArr.begin() + areaCount, [visAreaId](const CGameArea* a, const CGameArea* b) {
// if (a->x4_selfIdx == b->x4_selfIdx) {
// return false;
// }
// if (visAreaId == a->x4_selfIdx) {
// return false;
// }
// if (visAreaId == b->x4_selfIdx) {
// return true;
// }
// return CGraphics::g_ViewPoint.dot(a->GetAABB().center()) > CGraphics::g_ViewPoint.dot(b->GetAABB().center());
// });
//
// int pvsCount = 0;
// std::array<CPVSVisSet, 10> pvsArr;
// for (auto area = areaArr.cbegin(); area != areaArr.cbegin() + areaCount; ++area) {
// const CGameArea* areaPtr = *area;
// CPVSVisSet& pvsSet = pvsArr[pvsCount++];
// pvsSet.Reset(EPVSVisSetState::OutOfBounds);
// GetVisSetForArea(areaPtr->x4_selfIdx, visAreaId, pvsSet);
// }
//
// for (int i = areaCount - 1; i >= 0; --i) {
// const CGameArea& area = *areaArr[i];
// SetupFogForArea(area);
// g_Renderer->EnablePVS(pvsArr[i], area.x4_selfIdx);
// g_Renderer->SetWorldLightFadeLevel(area.GetPostConstructed()->x1128_worldLightingLevel);
// g_Renderer->UpdateAreaUniforms(area.x4_selfIdx, EWorldShadowMode::None, true, cubeInst * 6 + f);
// g_Renderer->DrawUnsortedGeometry(area.x4_selfIdx, 0x2, 0x0);
// }
//
// if (!SetupFogForDraw()) {
// g_Renderer->SetWorldFog(ERglFogMode::None, 0.f, 1.f, zeus::skBlack);
// }
//
// x850_world->DrawSky(zeus::CTransform::Translate(CGraphics::g_ViewPoint));
//
// for (int i = 0; i < areaCount; ++i) {
// const CGameArea& area = *areaArr[i];
// CPVSVisSet& pvs = pvsArr[i];
// SetupFogForArea(area);
// g_Renderer->SetWorldLightFadeLevel(area.GetPostConstructed()->x1128_worldLightingLevel);
// g_Renderer->EnablePVS(pvs, area.x4_selfIdx);
// g_Renderer->DrawSortedGeometry(area.x4_selfIdx, 0x2, 0x0);
// }
// }
//
// CGraphics::g_BooMainCommandQueue->generateMipmaps(actor.m_reflectionCube);
//
// CBooRenderer::BindMainDrawTarget();
// g_Renderer->SetViewport(backupVp.x0_left, backupVp.x4_top, backupVp.x8_width, backupVp.xc_height);
//
// ++cubeInst;
}
void CStateManager::DrawWorldCubeFaces() const {
size_t areaCount = 0;
std::array<const CGameArea*, 10> areaArr;
for (const CGameArea& area : *x850_world) {
if (areaCount == areaArr.size()) {
break;
}
auto occState = CGameArea::EOcclusionState::Occluded;
if (area.IsPostConstructed()) {
occState = area.GetOcclusionState();
}
if (occState == CGameArea::EOcclusionState::Visible) {
areaArr[areaCount++] = &area;
}
}
for (size_t ai = 0; ai < areaCount; ++ai) {
const CGameArea& area = *areaArr[ai];
int cubeInst = 0;
for (CEntity* ent : *area.GetAreaObjects()) {
if (const TCastToPtr<CActor> actor = ent) {
DrawActorCubeFaces(*actor, cubeInst);
}
}
}
}
void CStateManager::SetupFogForArea3XRange(TAreaId area) const { void CStateManager::SetupFogForArea3XRange(TAreaId area) const {
if (area == kInvalidAreaId) { if (area == kInvalidAreaId) {
area = x8cc_nextAreaId; area = x8cc_nextAreaId;
@ -2490,7 +2355,7 @@ void CStateManager::FrameBegin(s32 frameCount) {
x8d4_inputFrameIdx = frameCount; x8d4_inputFrameIdx = frameCount;
CTexture::SetCurrentFrameCount(frameCount); CTexture::SetCurrentFrameCount(frameCount);
CGraphicsPalette::SetCurrentFrameCount(frameCount); CGraphicsPalette::SetCurrentFrameCount(frameCount);
//SwapOutTexturesToARAM(2, 0x180000); // SwapOutTexturesToARAM(2, 0x180000);
} }
void CStateManager::InitializeState(CAssetId mlvlId, TAreaId aid, CAssetId mreaId) { void CStateManager::InitializeState(CAssetId mlvlId, TAreaId aid, CAssetId mreaId) {

View File

@ -18,7 +18,6 @@
#include "Runtime/Camera/CCameraManager.hpp" #include "Runtime/Camera/CCameraManager.hpp"
#include "Runtime/Camera/CCameraShakeData.hpp" #include "Runtime/Camera/CCameraShakeData.hpp"
#include "Runtime/GameObjectLists.hpp" #include "Runtime/GameObjectLists.hpp"
#include "Runtime/Graphics/Shaders/CColoredQuadFilter.hpp"
#include "Runtime/Input/CFinalInput.hpp" #include "Runtime/Input/CFinalInput.hpp"
#include "Runtime/Input/CRumbleManager.hpp" #include "Runtime/Input/CRumbleManager.hpp"
#include "Runtime/Weapon/CWeaponMgr.hpp" #include "Runtime/Weapon/CWeaponMgr.hpp"
@ -211,8 +210,6 @@ private:
bool xf94_29_cinematicPause : 1 = false; bool xf94_29_cinematicPause : 1 = false;
bool xf94_30_fullThreat : 1 = false; bool xf94_30_fullThreat : 1 = false;
CColoredQuadFilter m_deathWhiteout{EFilterType::Add};
CColoredQuadFilter m_escapeWhiteout{EFilterType::Add};
bool m_warping = false; bool m_warping = false;
std::map<TEditorId, std::set<SConnection>> m_incomingConnections; std::map<TEditorId, std::set<SConnection>> m_incomingConnections;
@ -258,11 +255,8 @@ public:
void DrawAdditionalFilters(); void DrawAdditionalFilters();
zeus::CFrustum SetupDrawFrustum(const SViewport& vp) const; zeus::CFrustum SetupDrawFrustum(const SViewport& vp) const;
zeus::CFrustum SetupViewForDraw(const SViewport& vp) const; zeus::CFrustum SetupViewForDraw(const SViewport& vp) const;
zeus::CFrustum SetupViewForCubeFaceDraw(const zeus::CVector3f& pos, int face) const;
void ResetViewAfterDraw(const SViewport& backupViewport, const zeus::CTransform& backupViewMatrix) const; void ResetViewAfterDraw(const SViewport& backupViewport, const zeus::CTransform& backupViewMatrix) const;
void DrawWorld(); void DrawWorld();
void DrawActorCubeFaces(CActor& actor, int& cubeInst) const;
void DrawWorldCubeFaces() const;
void SetupFogForArea3XRange(TAreaId area) const; void SetupFogForArea3XRange(TAreaId area) const;
void SetupFogForArea(TAreaId area) const; void SetupFogForArea(TAreaId area) const;
void SetupFogForAreaNonCurrent(TAreaId area) const; void SetupFogForAreaNonCurrent(TAreaId area) const;

View File

@ -4,10 +4,6 @@
#include "Runtime/GameGlobalObjects.hpp" #include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Graphics/CCubeRenderer.hpp" #include "Runtime/Graphics/CCubeRenderer.hpp"
#include "Runtime/Graphics/CGraphics.hpp" #include "Runtime/Graphics/CGraphics.hpp"
#include "Runtime/Graphics/Shaders/CColoredQuadFilter.hpp"
#include "Runtime/Graphics/Shaders/CRandomStaticFilter.hpp"
#include "Runtime/Graphics/Shaders/CScanLinesFilter.hpp"
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp"
#include "Runtime/Graphics/CGX.hpp" #include "Runtime/Graphics/CGX.hpp"
#include <algorithm> #include <algorithm>

View File

@ -682,16 +682,16 @@ void CCubeRenderer::SetPerspective(float fovy, float width, float height, float
std::pair<zeus::CVector2f, zeus::CVector2f> CCubeRenderer::SetViewportOrtho(bool centered, float znear, float zfar) { std::pair<zeus::CVector2f, zeus::CVector2f> CCubeRenderer::SetViewportOrtho(bool centered, float znear, float zfar) {
auto left = static_cast<float>(centered ? CGraphics::GetViewportLeft() - CGraphics::GetViewportHalfWidth() auto left = static_cast<float>(centered ? CGraphics::GetViewportLeft() - CGraphics::GetViewportHalfWidth()
: CGraphics::GetViewportLeft()); : CGraphics::GetViewportLeft());
auto top = static_cast<float>(centered ? CGraphics::GetViewportTop() - CGraphics::GetViewportHalfHeight() auto bottom = static_cast<float>(centered ? CGraphics::GetViewportTop() - CGraphics::GetViewportHalfHeight()
: CGraphics::GetViewportHeight()); : CGraphics::GetViewportTop());
auto right = static_cast<float>(CGraphics::GetViewportLeft() + auto right = static_cast<float>(CGraphics::GetViewportLeft() +
(centered ? CGraphics::GetViewportWidth() / 2 : CGraphics::GetViewportWidth())); (centered ? CGraphics::GetViewportWidth() / 2 : CGraphics::GetViewportWidth()));
auto bottom = static_cast<float>(CGraphics::GetViewportTop() + auto top = static_cast<float>(CGraphics::GetViewportTop() +
(centered ? CGraphics::GetViewportHeight() / 2 : CGraphics::GetViewportHeight())); (centered ? CGraphics::GetViewportHeight() / 2 : CGraphics::GetViewportHeight()));
CGraphics::SetOrtho(left, right, top, bottom, znear, zfar); CGraphics::SetOrtho(left, right, top, bottom, znear, zfar);
CGraphics::SetViewPointMatrix({}); CGraphics::SetViewPointMatrix({});
CGraphics::SetModelMatrix({}); CGraphics::SetModelMatrix({});
return {{left, top}, {right, bottom}}; return {{left, bottom}, {right, top}};
} }
void CCubeRenderer::SetClippingPlanes(const zeus::CFrustum& frustum) { x44_frustumPlanes = frustum; } void CCubeRenderer::SetClippingPlanes(const zeus::CFrustum& frustum) { x44_frustumPlanes = frustum; }
@ -896,6 +896,8 @@ void CCubeRenderer::SetThermal(bool thermal, float level, const zeus::CColor& co
void CCubeRenderer::SetThermalColdScale(float scale) { x2f8_thermColdScale = zeus::clamp(0.f, scale, 1.f); } void CCubeRenderer::SetThermalColdScale(float scale) { x2f8_thermColdScale = zeus::clamp(0.f, scale, 1.f); }
void CCubeRenderer::DoThermalBlendCold() { void CCubeRenderer::DoThermalBlendCold() {
SCOPED_GRAPHICS_DEBUG_GROUP("CCubeRenderer::DoThermalBlendCold", zeus::skBlue);
// Capture EFB // Capture EFB
x318_26_requestRGBA6 = true; x318_26_requestRGBA6 = true;
GXSetAlphaUpdate(true); GXSetAlphaUpdate(true);
@ -908,12 +910,14 @@ void CCubeRenderer::DoThermalBlendCold() {
// GXSetTexCopySrc(left, top, width, height); // GXSetTexCopySrc(left, top, width, height);
// GXSetTexCopyDst(width, height, GX::TF_I4, false); // GXSetTexCopyDst(width, height, GX::TF_I4, false);
// GXCopyTex(sSpareTextureData, true); // GXCopyTex(sSpareTextureData, true);
CGraphics::ResolveSpareTexture(aurora::gfx::ClipRect{ CGraphics::ResolveSpareTexture(
.x = static_cast<int32_t>(left), aurora::gfx::ClipRect{
.y = static_cast<int32_t>(top), .x = static_cast<int32_t>(left),
.width = static_cast<int32_t>(width), .y = static_cast<int32_t>(top),
.height = static_cast<int32_t>(height), .width = static_cast<int32_t>(width),
}, 0, GX::TF_I4); .height = static_cast<int32_t>(height),
},
0, GX::TF_I4);
// CGraphics::LoadDolphinSpareTexture(width, height, GX::TF_I4, nullptr, GX::TEXMAP7); // CGraphics::LoadDolphinSpareTexture(width, height, GX::TF_I4, nullptr, GX::TEXMAP7);
CGraphics::LoadDolphinSpareTexture(0, GX::TF_I4, GX::TEXMAP7); CGraphics::LoadDolphinSpareTexture(0, GX::TF_I4, GX::TEXMAP7);
@ -1019,14 +1023,7 @@ void CCubeRenderer::DoThermalBlendCold() {
} }
void CCubeRenderer::DoThermalBlendHot() { void CCubeRenderer::DoThermalBlendHot() {
CGX::SetNumIndStages(0); SCOPED_GRAPHICS_DEBUG_GROUP("CCubeRenderer::DoThermalBlendHot", zeus::skRed);
CGX::SetTevDirect(GX::TEVSTAGE0);
GXSetAlphaUpdate(true);
// CGraphics::SetProjectionState(backupProjectionState);
// CGraphics::SetViewPointMatrix(backupViewMatrix);
CDecal::SetMoveRedToAlphaBuffer(false);
CElementGen::SetMoveRedToAlphaBuffer(false);
return; // TODO
GXSetAlphaUpdate(false); GXSetAlphaUpdate(false);
GXSetDstAlpha(true, 0); GXSetDstAlpha(true, 0);
@ -1041,7 +1038,7 @@ void CCubeRenderer::DoThermalBlendHot() {
CGraphics::ResolveSpareTexture(CGraphics::g_Viewport, 0, GX::TF_I4); CGraphics::ResolveSpareTexture(CGraphics::g_Viewport, 0, GX::TF_I4);
x288_thermoPalette.Load(); x288_thermoPalette.Load();
// CGraphics::LoadDolphinSpareTexture(width, height, GX::TF_C4, GX::TLUT0, nullptr, GX::TEXMAP7); // CGraphics::LoadDolphinSpareTexture(width, height, GX::TF_C4, GX::TLUT0, nullptr, GX::TEXMAP7);
CGraphics::LoadDolphinSpareTexture(0, GX::TF_C4, GX::TEXMAP7); CGraphics::LoadDolphinSpareTexture(0, GX_TF_C4, GX_TLUT0, GX::TEXMAP7);
CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_TEXA, GX::CC_TEXC, GX::CC_ZERO); CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_TEXA, GX::CC_TEXC, GX::CC_ZERO);
CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_TEXA); CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_TEXA);
CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0); CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0);
@ -1080,7 +1077,14 @@ void CCubeRenderer::DoThermalBlendHot() {
GXTexCoord2f32(1.f, 0.f); GXTexCoord2f32(1.f, 0.f);
CGX::End(); CGX::End();
// move prologue here // Cleanup
CGX::SetNumIndStages(0);
CGX::SetTevDirect(GX::TEVSTAGE0);
GXSetAlphaUpdate(true);
CGraphics::SetProjectionState(backupProjectionState);
CGraphics::SetViewPointMatrix(backupViewMatrix);
CDecal::SetMoveRedToAlphaBuffer(false);
CElementGen::SetMoveRedToAlphaBuffer(false);
} }
u32 CCubeRenderer::GetStaticWorldDataSize() { u32 CCubeRenderer::GetStaticWorldDataSize() {

View File

@ -316,7 +316,13 @@ public:
} }
static void LoadDolphinSpareTexture(int bindIdx, GX::TextureFormat format, GX::TexMapID id) { static void LoadDolphinSpareTexture(int bindIdx, GX::TextureFormat format, GX::TexMapID id) {
GXTexObj obj; GXTexObj obj;
GXInitTexObjResolved(&obj, bindIdx, format, GX_CLAMP, GX_CLAMP); GXInitTexObjResolved(&obj, bindIdx, format, GX_CLAMP, GX_CLAMP, GX_TLUT0);
GXInitTexObjLOD(&obj, GX_NEAR, GX_NEAR, 0.f, 0.f, 0.f, false, false, GX_ANISO_1);
GXLoadTexObj(&obj, id);
}
static void LoadDolphinSpareTexture(int bindIdx, GXCITexFmt format, GXTlut tlut, GX::TexMapID id) {
GXTexObj obj;
GXInitTexObjResolved(&obj, bindIdx, static_cast<GX::TextureFormat>(format), GX_CLAMP, GX_CLAMP, tlut);
GXInitTexObjLOD(&obj, GX_NEAR, GX_NEAR, 0.f, 0.f, 0.f, false, false, GX_ANISO_1); GXInitTexObjLOD(&obj, GX_NEAR, GX_NEAR, 0.f, 0.f, 0.f, false, false, GX_ANISO_1);
GXLoadTexObj(&obj, id); GXLoadTexObj(&obj, id);
} }

View File

@ -26,8 +26,6 @@ set(GRAPHICS_SOURCES
CRainSplashGenerator.hpp CRainSplashGenerator.cpp CRainSplashGenerator.hpp CRainSplashGenerator.cpp
CFont.hpp CFont.cpp CFont.hpp CFont.cpp
Shaders/CLineRendererShaders.hpp Shaders/CLineRendererShaders.cpp Shaders/CLineRendererShaders.hpp Shaders/CLineRendererShaders.cpp
Shaders/CTexturedQuadFilter.hpp Shaders/CTexturedQuadFilter.cpp
Shaders/CColoredQuadFilter.hpp Shaders/CColoredQuadFilter.cpp
Shaders/CColoredStripShader.hpp Shaders/CColoredStripShader.cpp Shaders/CColoredStripShader.hpp Shaders/CColoredStripShader.cpp
Shaders/CModelShaders.hpp Shaders/CModelShaders.cpp Shaders/CModelShaders.hpp Shaders/CModelShaders.cpp
Shaders/CThermalColdFilter.hpp Shaders/CThermalColdFilter.cpp Shaders/CThermalColdFilter.hpp Shaders/CThermalColdFilter.cpp

View File

@ -4,6 +4,7 @@
#include "CDvdRequest.hpp" #include "CDvdRequest.hpp"
#include "Graphics/CGraphics.hpp" #include "Graphics/CGraphics.hpp"
#include "Graphics/CCubeRenderer.hpp" #include "Graphics/CCubeRenderer.hpp"
#include "Graphics/CGX.hpp"
#include "GameGlobalObjects.hpp" #include "GameGlobalObjects.hpp"
#include <amuse/DSPCodec.hpp> #include <amuse/DSPCodec.hpp>
@ -11,6 +12,110 @@
namespace metaforce { namespace metaforce {
static void MyTHPYuv2RgbTextureSetup(void* dataY, void* dataU, void* dataV, u16 width, u16 height) {
GXTexObj texV;
GXTexObj texU;
GXTexObj texY;
GXInitTexObj(&texY, dataY, width, height, GX::TF_I8, GX_CLAMP, GX_CLAMP, false);
GXInitTexObjLOD(&texY, GX_NEAR, GX_NEAR, 0.0, 0.0, 0.0, false, false, GX_ANISO_1);
GXLoadTexObj(&texY, GX::TEXMAP0);
GXInitTexObj(&texU, dataU, width / 2, height / 2, GX::TF_I8, GX_CLAMP, GX_CLAMP, false);
GXInitTexObjLOD(&texU, GX_NEAR, GX_NEAR, 0.0, 0.0, 0.0, false, false, GX_ANISO_1);
GXLoadTexObj(&texU, GX::TEXMAP1);
GXInitTexObj(&texV, dataV, width / 2, height / 2, GX::TF_I8, GX_CLAMP, GX_CLAMP, false);
GXInitTexObjLOD(&texV, GX_NEAR, GX_NEAR, 0.0, 0.0, 0.0, false, false, GX_ANISO_1);
GXLoadTexObj(&texV, GX::TEXMAP2);
CTexture::InvalidateTexMap(GX::TEXMAP0);
CTexture::InvalidateTexMap(GX::TEXMAP1);
CTexture::InvalidateTexMap(GX::TEXMAP2);
}
const std::array<u8, 32> InterlaceTex{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0,
};
static void MyTHPGXYuv2RgbSetup(bool interlaced2ndFrame, bool fieldFlip) {
CGX::SetZMode(true, GX::ALWAYS, false);
CGX::SetBlendMode(GX::BM_NONE, GX::BL_ONE, GX::BL_ZERO, GX::LO_CLEAR);
CGX::SetNumChans(0);
CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY);
CGX::SetTexCoordGen(GX::TEXCOORD1, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY);
if (!fieldFlip) {
CGX::SetNumTexGens(3);
CGX::SetTexCoordGen(GX::TEXCOORD2, GX::TG_MTX2x4, GX::TG_POS, GX::TEXMTX0, false, GX::PTIDENTITY);
aurora::Mat4x2<float> mtx;
mtx.m0.x = 0.125f;
mtx.m2.y = 0.25f;
if (interlaced2ndFrame) {
mtx.m3.y = 0.25f;
}
GXLoadTexMtxImm(&mtx, GX::TEXMTX0, GX::MTX2x4);
GXTexObj texObj;
GXInitTexObj(&texObj, InterlaceTex.data(), 8, 4, GX::TF_I8, GX_REPEAT, GX_REPEAT, false);
GXInitTexObjLOD(&texObj, GX_NEAR, GX_NEAR, 0.f, 0.f, 0.f, false, false, GX_ANISO_1);
GXLoadTexObj(&texObj, GX::TEXMAP3);
CTexture::InvalidateTexMap(GX::TEXMAP3);
CGX::SetTevOrder(GX::TEVSTAGE4, GX::TEXCOORD2, GX::TEXMAP3, GX::COLOR_NULL);
CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE4);
CGX::SetTevColorIn(GX::TEVSTAGE4, GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_CPREV);
CGX::SetTevAlphaIn(GX::TEVSTAGE4, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_TEXA);
CGX::SetAlphaCompare(GX::LESS, 128, GX::AOP_AND, GX::ALWAYS, 0);
CGX::SetNumTevStages(5);
} else {
CGX::SetNumTexGens(2);
CGX::SetNumTevStages(4);
}
constexpr std::array vtxDescList{
GX::VtxDescList{GX::VA_POS, GX::DIRECT},
GX::VtxDescList{GX::VA_TEX0, GX::DIRECT},
GX::VtxDescList{},
};
CGX::SetVtxDescv(vtxDescList.data());
GXSetColorUpdate(true);
GXSetAlphaUpdate(false);
GXInvalidateTexAll();
GXSetVtxAttrFmt(GX::VTXFMT7, GX::VA_POS, GX::CLR_RGBA, GX::F32, 0);
GXSetVtxAttrFmt(GX::VTXFMT7, GX::VA_TEX0, GX::CLR_RGBA, GX::RGBX8, 0);
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD1, GX::TEXMAP1, GX::COLOR_NULL);
CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_TEXC, GX::CC_KONST, GX::CC_C0);
CGX::SetTevColorOp(GX::TEVSTAGE0, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, false, GX::TEVPREV);
CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_TEXA, GX::CA_KONST, GX::CA_A0);
CGX::SetTevAlphaOp(GX::TEVSTAGE0, GX::TEV_SUB, GX::TB_ZERO, GX::CS_SCALE_1, false, GX::TEVPREV);
CGX::SetTevKColorSel(GX::TEVSTAGE0, GX::TEV_KCSEL_K0);
CGX::SetTevKAlphaSel(GX::TEVSTAGE0, GX::TEV_KASEL_K0_A);
CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD1, GX::TEXMAP2, GX::COLOR_NULL);
CGX::SetTevColorIn(GX::TEVSTAGE1, GX::CC_ZERO, GX::CC_TEXC, GX::CC_KONST, GX::CC_CPREV);
CGX::SetTevColorOp(GX::TEVSTAGE1, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_2, false, GX::TEVPREV);
CGX::SetTevAlphaIn(GX::TEVSTAGE1, GX::CA_ZERO, GX::CA_TEXA, GX::CA_KONST, GX::CA_APREV);
CGX::SetTevAlphaOp(GX::TEVSTAGE1, GX::TEV_SUB, GX::TB_ZERO, GX::CS_SCALE_1, false, GX::TEVPREV);
CGX::SetTevKColorSel(GX::TEVSTAGE1, GX::TEV_KCSEL_K1);
CGX::SetTevKAlphaSel(GX::TEVSTAGE1, GX::TEV_KASEL_K1_A);
CGX::SetTevOrder(GX::TEVSTAGE2, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL);
CGX::SetTevColorIn(GX::TEVSTAGE2, GX::CC_ZERO, GX::CC_TEXC, GX::CC_ONE, GX::CC_CPREV);
CGX::SetTevColorOp(GX::TEVSTAGE2, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV);
CGX::SetTevAlphaIn(GX::TEVSTAGE2, GX::CA_TEXA, GX::CA_ZERO, GX::CA_ZERO, GX::CA_APREV);
CGX::SetTevAlphaOp(GX::TEVSTAGE2, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV);
CGX::SetTevOrder(GX::TEVSTAGE3, GX::TEXCOORD_NULL, GX::TEXMAP_NULL, GX::COLOR_NULL);
CGX::SetTevColorIn(GX::TEVSTAGE3, GX::CC_APREV, GX::CC_CPREV, GX::CC_KONST, GX::CC_ZERO);
CGX::SetTevColorOp(GX::TEVSTAGE3, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV);
CGX::SetTevAlphaIn(GX::TEVSTAGE3, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO);
CGX::SetTevAlphaOp(GX::TEVSTAGE3, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, true, GX::TEVPREV);
CGX::SetTevKColorSel(GX::TEVSTAGE3, GX::TEV_KCSEL_K2);
GXSetTevColorS10(GX::TEVREG0, 0xffa60000ff8e0087u);
CGX::SetTevKColor(GX::KCOLOR0, zeus::Comp32(0x0000e258));
CGX::SetTevKColor(GX::KCOLOR1, zeus::Comp32(0xb30000b6));
CGX::SetTevKColor(GX::KCOLOR2, zeus::Comp32(0xff00ff80));
}
static void MyTHPGXRestore() {
CGX::SetZMode(true, GX::ALWAYS, false);
CGX::SetBlendMode(GX::BM_NONE, GX::BL_ONE, GX::BL_ZERO, GX::LO_SET);
CGX::SetNumTexGens(1);
CGX::SetNumChans(0);
CGX::SetNumTevStages(1);
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL);
CGX::SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_AND, GX::ALWAYS, 0);
}
/* used in the original to look up fixed-point dividends on a /* used in the original to look up fixed-point dividends on a
* MIDI-style volume scale (0-127) -> (n/0x8000) */ * MIDI-style volume scale (0-127) -> (n/0x8000) */
static const std::array<u16, 128> StaticVolumeLookup = { static const std::array<u16, 128> StaticVolumeLookup = {
@ -359,29 +464,92 @@ void CMoviePlayer::Rewind() {
xe8_curSeconds = 0.f; xe8_curSeconds = 0.f;
} }
void CMoviePlayer::Draw() { bool CMoviePlayer::DrawVideo() {
// TODO
// if (!xa0_bufferQueue.empty()) {
// return false;
// }
g_Renderer->SetDepthReadWrite(false, false);
g_Renderer->SetViewportOrtho(false, -4096.f, 4096.f);
const s32 vpHeight = CGraphics::GetViewportHeight();
const s32 vpWidth = CGraphics::GetViewportWidth();
const s32 vpTop = CGraphics::GetViewportTop();
const s32 vpLeft = CGraphics::GetViewportLeft();
const s32 vidWidth = x6c_videoInfo.width;
const s32 vidHeight = x6c_videoInfo.height;
const s32 centerX = (vidWidth - vpWidth) / 2;
const s32 centerY = (vidHeight - vpHeight) / 2;
const s32 vl = vpLeft - centerX;
const s32 vr = vpLeft + vpWidth + centerX;
const s32 vb = vpTop + vpHeight + centerY;
const s32 vt = vpTop - centerY;
aurora::Vec3<float> v1;
aurora::Vec3<float> v2;
aurora::Vec3<float> v3;
aurora::Vec3<float> v4;
v1.x = vl;
v1.y = 0.0;
v1.z = vb;
v2.x = vr;
v2.y = 0.0;
v2.z = vb;
v3.x = vl;
v3.y = 0.0;
v3.z = vt;
v4.x = vr;
v4.y = 0.0;
v4.z = vt;
DrawFrame(v1, v2, v3, v4);
return true;
}
void CMoviePlayer::DrawFrame(const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3,
const zeus::CVector3f& v4) {
if (xd0_drawTexSlot == UINT32_MAX || !GetIsFullyCached()) { if (xd0_drawTexSlot == UINT32_MAX || !GetIsFullyCached()) {
return; return;
} }
SCOPED_GRAPHICS_DEBUG_GROUP("CMoviePlayer::DrawFrame", zeus::skYellow); SCOPED_GRAPHICS_DEBUG_GROUP("CMoviePlayer::DrawFrame", zeus::skYellow);
/* Correct movie aspect ratio */ CGraphics::SetUseVideoFilter(xf4_26_fieldFlip);
float hPad, vPad;
if (CGraphics::GetViewportAspect() >= 1.78f) {
hPad = 1.78f / CGraphics::GetViewportAspect();
vPad = 1.78f / 1.33f;
} else {
hPad = 1.f;
vPad = CGraphics::GetViewportAspect() / 1.33f;
}
/* draw appropriate field */ /* Correct movie aspect ratio */
CTHPTextureSet& tex = x80_textures[xd0_drawTexSlot]; // float hPad, vPad;
aurora::gfx::queue_movie_player(tex.Y[m_deinterlace ? (xfc_fieldIndex != 0) : 0], tex.U, tex.V, hPad, vPad); // if (CGraphics::GetViewportAspect() >= 1.78f) {
// hPad = 1.78f / CGraphics::GetViewportAspect();
// vPad = 1.78f / 1.33f;
// } else {
// hPad = 1.f;
// vPad = CGraphics::GetViewportAspect() / 1.33f;
// }
//
// /* draw appropriate field */
// CTHPTextureSet& tex = x80_textures[xd0_drawTexSlot];
// aurora::gfx::queue_movie_player(tex.Y[m_deinterlace ? (xfc_fieldIndex != 0) : 0], tex.U, tex.V, hPad, vPad);
MyTHPGXYuv2RgbSetup(CGraphics::g_LastFrameUsedAbove, xf4_26_fieldFlip);
uintptr_t planeSize = x6c_videoInfo.width * x6c_videoInfo.height;
uintptr_t planeSizeQuarter = planeSize / 4;
MyTHPYuv2RgbTextureSetup(m_yuvBuf.get(), m_yuvBuf.get() + planeSize, m_yuvBuf.get() + planeSize + planeSizeQuarter,
x6c_videoInfo.width, x6c_videoInfo.height);
CGX::Begin(GX::TRIANGLEFAN, GX::VTXFMT7, 4);
GXPosition3f32(v1);
GXTexCoord2f32(0.f, 0.f);
GXPosition3f32(v3);
GXTexCoord2f32(0.f, 1.f);
GXPosition3f32(v4);
GXTexCoord2f32(1.f, 1.f);
GXPosition3f32(v2);
GXTexCoord2f32(1.f, 0.f);
CGX::End();
MyTHPGXRestore();
/* ensure second field is being displayed by VI to signal advance /* ensure second field is being displayed by VI to signal advance
* (faked in metaforce with continuous xor) */ * (faked in metaforce with continuous xor) */
if (!xfc_fieldIndex && CGraphics::g_LastFrameUsedAbove) if (xfc_fieldIndex == 0 && CGraphics::g_LastFrameUsedAbove)
xf4_26_fieldFlip = true; xf4_26_fieldFlip = true;
++xfc_fieldIndex; ++xfc_fieldIndex;
@ -487,29 +655,29 @@ void CMoviePlayer::DecodeFromRead(const void* data) {
tjDecompressToYUV(TjHandle, (u8*)inptr, frameHeader.imageSize, m_yuvBuf.get(), 0); tjDecompressToYUV(TjHandle, (u8*)inptr, frameHeader.imageSize, m_yuvBuf.get(), 0);
inptr += frameHeader.imageSize; inptr += frameHeader.imageSize;
uintptr_t planeSize = x6c_videoInfo.width * x6c_videoInfo.height; // uintptr_t planeSize = x6c_videoInfo.width * x6c_videoInfo.height;
uintptr_t planeSizeHalf = planeSize / 2; // uintptr_t planeSizeHalf = planeSize / 2;
uintptr_t planeSizeQuarter = planeSizeHalf / 2; // uintptr_t planeSizeQuarter = planeSizeHalf / 2;
if (m_deinterlace) { // if (m_deinterlace) {
/* Deinterlace into 2 discrete 60-fps half-res textures */ // /* Deinterlace into 2 discrete 60-fps half-res textures */
auto buffer = std::make_unique<u8[]>(planeSizeHalf); // auto buffer = std::make_unique<u8[]>(planeSizeHalf);
for (unsigned y = 0; y < x6c_videoInfo.height / 2; ++y) { // for (unsigned y = 0; y < x6c_videoInfo.height / 2; ++y) {
memcpy(buffer.get() + x6c_videoInfo.width * y, m_yuvBuf.get() + x6c_videoInfo.width * (y * 2), // memcpy(buffer.get() + x6c_videoInfo.width * y, m_yuvBuf.get() + x6c_videoInfo.width * (y * 2),
x6c_videoInfo.width); // x6c_videoInfo.width);
} // }
aurora::gfx::write_texture(*tex.Y[0], {buffer.get(), planeSizeHalf}); // aurora::gfx::write_texture(*tex.Y[0], {buffer.get(), planeSizeHalf});
for (unsigned y = 0; y < x6c_videoInfo.height / 2; ++y) { // for (unsigned y = 0; y < x6c_videoInfo.height / 2; ++y) {
memcpy(buffer.get() + x6c_videoInfo.width * y, m_yuvBuf.get() + x6c_videoInfo.width * (y * 2 + 1), // memcpy(buffer.get() + x6c_videoInfo.width * y, m_yuvBuf.get() + x6c_videoInfo.width * (y * 2 + 1),
x6c_videoInfo.width); // x6c_videoInfo.width);
} // }
aurora::gfx::write_texture(*tex.Y[1], {buffer.get(), planeSizeHalf}); // aurora::gfx::write_texture(*tex.Y[1], {buffer.get(), planeSizeHalf});
} else { // } else {
/* Direct planar load */ // /* Direct planar load */
aurora::gfx::write_texture(*tex.Y[0], {m_yuvBuf.get(), planeSize}); // aurora::gfx::write_texture(*tex.Y[0], {m_yuvBuf.get(), planeSize});
} // }
aurora::gfx::write_texture(*tex.U, {m_yuvBuf.get() + planeSize, planeSizeQuarter}); // aurora::gfx::write_texture(*tex.U, {m_yuvBuf.get() + planeSize, planeSizeQuarter});
aurora::gfx::write_texture(*tex.V, {m_yuvBuf.get() + planeSize + planeSizeQuarter, planeSizeQuarter}); // aurora::gfx::write_texture(*tex.V, {m_yuvBuf.get() + planeSize + planeSizeQuarter, planeSizeQuarter});
break; break;
} }

View File

@ -136,9 +136,12 @@ public:
float GetPlayedSeconds() const { return xdc_frameRem + xe8_curSeconds; } float GetPlayedSeconds() const { return xdc_frameRem + xe8_curSeconds; }
float GetTotalSeconds() const { return xe4_totalSeconds; } float GetTotalSeconds() const { return xe4_totalSeconds; }
void SetPlayMode(EPlayMode mode) { xe0_playMode = mode; } void SetPlayMode(EPlayMode mode) { xe0_playMode = mode; }
void Draw(); bool DrawVideo();
void DrawFrame(const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3,
const zeus::CVector3f& v4);
void Update(float dt); void Update(float dt);
std::pair<u32, u32> GetVideoDimensions() const { return {x6c_videoInfo.width, x6c_videoInfo.height}; } u32 GetWidth() const { return x6c_videoInfo.width; }
u32 GetHeight() const { return x6c_videoInfo.width; }
static void Initialize(); static void Initialize();
static void Shutdown(); static void Shutdown();

View File

@ -19,29 +19,40 @@ zeus::CAABox CSimpleShadow::GetMaxShadowBox(const zeus::CAABox& aabb) const {
zeus::CAABox CSimpleShadow::GetBounds() const { zeus::CAABox CSimpleShadow::GetBounds() const {
float extent = x34_radius * x30_scale; float extent = x34_radius * x30_scale;
return {{x0_xf.origin.x() - extent, x0_xf.origin.y() - extent, x0_xf.origin.z() - extent}, return {
{x0_xf.origin.x() + extent, x0_xf.origin.y() + extent, x0_xf.origin.z() + extent}}; {x0_xf.origin.x() - extent, x0_xf.origin.y() - extent, x0_xf.origin.z() - extent},
{x0_xf.origin.x() + extent, x0_xf.origin.y() + extent, x0_xf.origin.z() + extent},
};
} }
void CSimpleShadow::Render(const TLockedToken<CTexture>& tex) { void CSimpleShadow::Render(TLockedToken<CTexture>& tex) {
if (!x48_24_collision) if (!x48_24_collision)
return; return;
SCOPED_GRAPHICS_DEBUG_GROUP("CSimpleShadow::Render", zeus::skGrey); SCOPED_GRAPHICS_DEBUG_GROUP("CSimpleShadow::Render", zeus::skGrey);
CGraphics::DisableAllLights(); CGraphics::DisableAllLights();
CGraphics::SetModelMatrix(x0_xf); CGraphics::SetModelMatrix(x0_xf);
tex->Load(GX::TEXMAP0, EClampMode::Repeat);
//if (!m_filter || m_filter->GetTex().GetObj() != tex.GetObj()) CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc);
//m_filter.emplace(EFilterType::InvDstMultiply, tex, CTexturedQuadFilter::ZTest::LEqual); CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, false);
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha,
ERglLogicOp::Clear);
CGraphics::StreamBegin(GX::QUADS);
float radius = x34_radius * x30_scale; float radius = x34_radius * x30_scale;
const std::array<CTexturedQuadFilter::Vert, 4> verts{{ float t = x3c_heightAlpha * x38_userAlpha;
{{-radius, 0.f, -radius}, {0.f, 0.f}}, CGraphics::StreamColor(zeus::CColor{t, t} /* TODO double check */);
{{radius, 0.f, -radius}, {0.f, 1.f}}, CGraphics::StreamTexcoord(0.f, 0.f);
{{-radius, 0.f, radius}, {1.f, 0.f}}, CGraphics::StreamVertex(-radius, 0.f, -radius);
{{radius, 0.f, radius}, {1.f, 1.f}}, CGraphics::StreamTexcoord(0.f, 1.f);
}}; CGraphics::StreamVertex(radius, 0.f, -radius);
//m_filter->drawVerts(zeus::skWhite, verts); CGraphics::StreamTexcoord(1.f, 1.f);
CGraphics::StreamVertex(radius, 0.f, radius);
CGraphics::StreamTexcoord(1.f, 0.f);
CGraphics::StreamVertex(-radius, 0.f, radius);
CGraphics::StreamEnd();
} }
void CSimpleShadow::Calculate(const zeus::CAABox& aabb, const zeus::CTransform& xf, const CStateManager& mgr) { void CSimpleShadow::Calculate(const zeus::CAABox& aabb, const zeus::CTransform& xf, const CStateManager& mgr) {

View File

@ -1,8 +1,9 @@
#pragma once #pragma once
#include <optional> #include "Runtime/CToken.hpp"
#include "Runtime/Graphics/CTexture.hpp"
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp" #include <optional>
#include <zeus/CAABox.hpp> #include <zeus/CAABox.hpp>
#include <zeus/CTransform.hpp> #include <zeus/CTransform.hpp>
@ -22,7 +23,6 @@ class CSimpleShadow {
bool x48_24_collision : 1 = false; bool x48_24_collision : 1 = false;
bool x48_25_alwaysCalculateRadius : 1 = true; bool x48_25_alwaysCalculateRadius : 1 = true;
bool x48_26_radiusCalculated : 1 = false; bool x48_26_radiusCalculated : 1 = false;
std::optional<CTexturedQuadFilter> m_filter;
public: public:
CSimpleShadow(float scale, float userAlpha, float maxObjHeight, float displacement); CSimpleShadow(float scale, float userAlpha, float maxObjHeight, float displacement);
@ -33,7 +33,7 @@ public:
float GetMaxObjectHeight() const { return x40_maxObjHeight; } float GetMaxObjectHeight() const { return x40_maxObjHeight; }
void SetUserAlpha(float a) { x38_userAlpha = a; } void SetUserAlpha(float a) { x38_userAlpha = a; }
const zeus::CTransform& GetTransform() const { return x0_xf; } const zeus::CTransform& GetTransform() const { return x0_xf; }
void Render(const TLockedToken<CTexture>& tex); void Render(TLockedToken<CTexture>& tex);
void Calculate(const zeus::CAABox& aabb, const zeus::CTransform& xf, const CStateManager& mgr); void Calculate(const zeus::CAABox& aabb, const zeus::CTransform& xf, const CStateManager& mgr);
}; };
} // namespace metaforce } // namespace metaforce

View File

@ -741,6 +741,19 @@ enum DistAttnFn {
using GXColor = zeus::CColor; using GXColor = zeus::CColor;
using GXBool = bool; using GXBool = bool;
struct GXColorS10 {
s16 r;
s16 g;
s16 b;
s16 a;
constexpr GXColorS10(u64 c) noexcept
: r(static_cast<s16>((c >> 48) & 0xFFFF))
, g(static_cast<s16>((c >> 32) & 0xFFFF))
, b(static_cast<s16>((c >> 16) & 0xFFFF))
, a(static_cast<s16>(c & 0xFFFF)) {}
};
enum GXTlutFmt { enum GXTlutFmt {
GX_TL_IA8 = 0x0, GX_TL_IA8 = 0x0,
GX_TL_RGB565 = 0x1, GX_TL_RGB565 = 0x1,
@ -845,7 +858,9 @@ void GXSetCullMode(GX::CullMode mode) noexcept;
void GXSetBlendMode(GX::BlendMode mode, GX::BlendFactor src, GX::BlendFactor dst, GX::LogicOp op) noexcept; void GXSetBlendMode(GX::BlendMode mode, GX::BlendFactor src, GX::BlendFactor dst, GX::LogicOp op) noexcept;
void GXSetZMode(GXBool compare_enable, GX::Compare func, GXBool update_enable) noexcept; void GXSetZMode(GXBool compare_enable, GX::Compare func, GXBool update_enable) noexcept;
void GXSetTevColor(GX::TevRegID id, const GXColor& color) noexcept; void GXSetTevColor(GX::TevRegID id, const GXColor& color) noexcept;
void GXSetTevColorS10(GX::TevRegID id, const GXColorS10& color) noexcept;
void GXSetTevKColor(GX::TevKColorID id, const GXColor& color) noexcept; void GXSetTevKColor(GX::TevKColorID id, const GXColor& color) noexcept;
void GXSetColorUpdate(GXBool enabled) noexcept;
void GXSetAlphaUpdate(GXBool enabled) noexcept; void GXSetAlphaUpdate(GXBool enabled) noexcept;
void GXSetDstAlpha(GXBool enabled, u8 value) noexcept; void GXSetDstAlpha(GXBool enabled, u8 value) noexcept;
void GXSetCopyClear(const GXColor& color, float depth) noexcept; void GXSetCopyClear(const GXColor& color, float depth) noexcept;
@ -898,7 +913,7 @@ void GXInitTexObj(GXTexObj* obj, const void* data, u16 width, u16 height, GX::Te
GXTexWrapMode wrapT, GXBool mipmap) noexcept; GXTexWrapMode wrapT, GXBool mipmap) noexcept;
// Addition for binding render textures // Addition for binding render textures
void GXInitTexObjResolved(GXTexObj* obj, u32 bindIdx, GX::TextureFormat format, GXTexWrapMode wrapS, void GXInitTexObjResolved(GXTexObj* obj, u32 bindIdx, GX::TextureFormat format, GXTexWrapMode wrapS,
GXTexWrapMode wrapT); GXTexWrapMode wrapT, GXTlut tlut);
void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter minFilt, GXTexFilter magFilt, float minLod, float maxLod, float lodBias, void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter minFilt, GXTexFilter magFilt, float minLod, float maxLod, float lodBias,
GXBool biasClamp, GXBool doEdgeLod, GXAnisotropy maxAniso) noexcept; GXBool biasClamp, GXBool doEdgeLod, GXAnisotropy maxAniso) noexcept;
void GXInitTexObjCI(GXTexObj* obj, void* data, u16 width, u16 height, GXCITexFmt format, GXTexWrapMode wrapS, void GXInitTexObjCI(GXTexObj* obj, void* data, u16 width, u16 height, GXCITexFmt format, GXTexWrapMode wrapS,
@ -912,6 +927,7 @@ void GXSetTexCopyDst(u16 wd, u16 ht, GX::TextureFormat fmt, GXBool mipmap) noexc
u32 GXGetTexBufferSize(u16 width, u16 height, u32 fmt, GXBool mips, u8 maxLod) noexcept; u32 GXGetTexBufferSize(u16 width, u16 height, u32 fmt, GXBool mips, u8 maxLod) noexcept;
void GXCopyTex(void* dest, GXBool clear) noexcept; void GXCopyTex(void* dest, GXBool clear) noexcept;
static inline void GXPixModeSync() noexcept {} // no-op static inline void GXPixModeSync() noexcept {} // no-op
void GXInvalidateTexAll() noexcept;
void GXSetIndTexMtx(GX::IndTexMtxID id, const void* mtx /* Mat4x2<float> */, s8 scaleExp) noexcept; void GXSetIndTexMtx(GX::IndTexMtxID id, const void* mtx /* Mat4x2<float> */, s8 scaleExp) noexcept;
void GXSetTevIndirect(GX::TevStageID tevStage, GX::IndTexStageID indStage, GX::IndTexFormat fmt, void GXSetTevIndirect(GX::TevStageID tevStage, GX::IndTexStageID indStage, GX::IndTexFormat fmt,
GX::IndTexBiasSel biasSel, GX::IndTexMtxID matrixSel, GX::IndTexWrap wrapS, GX::IndTexWrap wrapT, GX::IndTexBiasSel biasSel, GX::IndTexMtxID matrixSel, GX::IndTexWrap wrapS, GX::IndTexWrap wrapT,

View File

@ -76,10 +76,10 @@ void CWorldShadowShader::lightenShadow() {
void CWorldShadowShader::blendPreviousShadow() { void CWorldShadowShader::blendPreviousShadow() {
SCOPED_GRAPHICS_DEBUG_GROUP("CWorldShadowShader::blendPreviousShadow", zeus::skMagenta); SCOPED_GRAPHICS_DEBUG_GROUP("CWorldShadowShader::blendPreviousShadow", zeus::skMagenta);
if (!m_prevQuad) // if (!m_prevQuad)
m_prevQuad.emplace(EFilterType::Blend, m_tex); // m_prevQuad.emplace(EFilterType::Blend, m_tex);
zeus::CRectangle rect(0.f, 1.f, 1.f, -1.f); // zeus::CRectangle rect(0.f, 1.f, 1.f, -1.f);
m_prevQuad->draw({1.f, 0.85f}, 1.f, rect); // m_prevQuad->draw({1.f, 0.85f}, 1.f, rect);
} }
void CWorldShadowShader::resolveTexture() { void CWorldShadowShader::resolveTexture() {

View File

@ -3,7 +3,6 @@
#include <optional> #include <optional>
#include "Runtime/GCNTypes.hpp" #include "Runtime/GCNTypes.hpp"
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp"
//#include <boo/graphicsdev/IGraphicsDataFactory.hpp> //#include <boo/graphicsdev/IGraphicsDataFactory.hpp>
@ -13,8 +12,8 @@
namespace metaforce { namespace metaforce {
class CWorldShadowShader { class CWorldShadowShader {
aurora::gfx::TextureHandle m_tex; // aurora::gfx::TextureHandle m_tex;
std::optional<CTexturedQuadFilter> m_prevQuad; // std::optional<CTexturedQuadFilter> m_prevQuad;
u32 m_w, m_h; u32 m_w, m_h;
struct Uniform { struct Uniform {
@ -40,7 +39,7 @@ public:
u32 GetWidth() const { return m_w; } u32 GetWidth() const { return m_w; }
u32 GetHeight() const { return m_h; } u32 GetHeight() const { return m_h; }
const aurora::gfx::TextureHandle& GetTexture() const { return m_tex; } // const aurora::gfx::TextureHandle& GetTexture() const { return m_tex; }
}; };
} // namespace metaforce } // namespace metaforce

View File

@ -4,7 +4,6 @@
#include "Runtime/CToken.hpp" #include "Runtime/CToken.hpp"
#include "Runtime/rstl.hpp" #include "Runtime/rstl.hpp"
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp"
#include "Runtime/GuiSys/CGuiWidget.hpp" #include "Runtime/GuiSys/CGuiWidget.hpp"
#include <zeus/CVector2f.hpp> #include <zeus/CVector2f.hpp>

View File

@ -322,8 +322,9 @@ void CHudDecoInterfaceScan::Update(float dt, const CStateManager& stateMgr) {
} }
void CHudDecoInterfaceScan::Draw() { void CHudDecoInterfaceScan::Draw() {
SCOPED_GRAPHICS_DEBUG_GROUP("CHudDecoInterfaceScan::Draw", zeus::skGreen);
x18_scanDisplay.Draw(); x18_scanDisplay.Draw();
if (x10_loadedScanHudFlat) { if (x10_loadedScanHudFlat != nullptr) {
x10_loadedScanHudFlat->Draw(CGuiWidgetDrawParms::Default()); x10_loadedScanHudFlat->Draw(CGuiWidgetDrawParms::Default());
} }
} }

View File

@ -36,23 +36,25 @@ void CScanDisplay::CDataDot::Update(float dt) {
} }
void CScanDisplay::CDataDot::Draw(const zeus::CColor& col, float radius) { void CScanDisplay::CDataDot::Draw(const zeus::CColor& col, float radius) {
if (x24_alpha == 0.f) { if (x24_alpha == 0.f || x0_dotState == EDotState::Hidden) {
return; return;
} }
if (x0_dotState != EDotState::Hidden) { const zeus::CTransform xf = zeus::CTransform::Translate(xc_curPos.x(), 0.f, xc_curPos.y());
const zeus::CTransform xf = zeus::CTransform::Translate(xc_curPos.x(), 0.f, xc_curPos.y()); g_Renderer->SetModelMatrix(xf);
CGraphics::SetModelMatrix(xf); CGraphics::StreamBegin(GX::TRIANGLESTRIP);
zeus::CColor useColor = col; zeus::CColor useColor = col;
useColor.a() *= x24_alpha; useColor.a() *= x24_alpha;
const std::array<CTexturedQuadFilter::Vert, 4> verts{{ CGraphics::StreamColor(useColor);
{{-radius, 0.f, radius}, {0.f, 1.f}}, CGraphics::StreamTexcoord(0.f, 1.f);
{{-radius, 0.f, -radius}, {0.f, 0.f}}, CGraphics::StreamVertex(-radius, 0.f, radius);
{{radius, 0.f, radius}, {1.f, 1.f}}, CGraphics::StreamTexcoord(0.f, 0.f);
{{radius, 0.f, -radius}, {1.f, 0.f}}, CGraphics::StreamVertex(-radius, 0.f, -radius);
}}; CGraphics::StreamTexcoord(1.f, 1.f);
m_quad.drawVerts(useColor, verts); CGraphics::StreamVertex(radius, 0.f, radius);
} CGraphics::StreamTexcoord(1.f, 0.f);
CGraphics::StreamVertex(radius, 0.f, -radius);
CGraphics::StreamEnd();
} }
void CScanDisplay::CDataDot::StartTransitionTo(const zeus::CVector2f& vec, float dur) { void CScanDisplay::CDataDot::StartTransitionTo(const zeus::CVector2f& vec, float dur) {
@ -444,10 +446,13 @@ void CScanDisplay::Draw() {
if (!x0_dataDot.IsLoaded()) { if (!x0_dataDot.IsLoaded()) {
return; return;
} }
SCOPED_GRAPHICS_DEBUG_GROUP("CScanDisplay::Draw", zeus::skGreen);
// No Z-test or write g_Renderer->SetDepthReadWrite(false, false);
g_Renderer->SetViewportOrtho(true, -4096.f, 4096.f); g_Renderer->SetViewportOrtho(true, -4096.f, 4096.f);
// Additive alpha g_Renderer->SetBlendMode_AdditiveAlpha();
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc);
x0_dataDot->Load(GX::TEXMAP0, EClampMode::Repeat);
const float vpRatio = CGraphics::GetViewportHeight() / 480.f; const float vpRatio = CGraphics::GetViewportHeight() / 480.f;
for (CDataDot& dot : xbc_dataDots) { for (CDataDot& dot : xbc_dataDots) {

View File

@ -8,7 +8,6 @@
#include "Runtime/rstl.hpp" #include "Runtime/rstl.hpp"
#include "Runtime/Camera/CCameraFilter.hpp" #include "Runtime/Camera/CCameraFilter.hpp"
#include "Runtime/Graphics/CTexture.hpp" #include "Runtime/Graphics/CTexture.hpp"
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp"
#include <zeus/CColor.hpp> #include <zeus/CColor.hpp>
#include <zeus/CQuaternion.hpp> #include <zeus/CQuaternion.hpp>
@ -40,10 +39,9 @@ public:
float x20_remTime = 0.f; float x20_remTime = 0.f;
float x24_alpha = 0.f; float x24_alpha = 0.f;
float x28_desiredAlpha = 0.f; float x28_desiredAlpha = 0.f;
CTexturedQuadFilter m_quad;
public: public:
explicit CDataDot(const TLockedToken<CTexture>& dataDotTex) : m_quad(EFilterType::Add, dataDotTex) {} explicit CDataDot(const TLockedToken<CTexture>& dataDotTex) {}
void Update(float dt); void Update(float dt);
void Draw(const zeus::CColor& color, float radius); void Draw(const zeus::CColor& color, float radius);
float GetTransitionFactor() const { return x1c_transDur > 0.f ? x20_remTime / x1c_transDur : 0.f; } float GetTransitionFactor() const { return x1c_transDur > 0.f ? x20_remTime / x1c_transDur : 0.f; }

View File

@ -3,7 +3,6 @@
#include "Runtime/CIOWin.hpp" #include "Runtime/CIOWin.hpp"
#include "Runtime/CToken.hpp" #include "Runtime/CToken.hpp"
#include "Runtime/Graphics/CTexture.hpp" #include "Runtime/Graphics/CTexture.hpp"
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp"
namespace metaforce { namespace metaforce {

View File

@ -198,20 +198,17 @@ CIOWin::EMessageReturn CCredits::ProcessUserInput(const CFinalInput& input) {
} }
void CCredits::DrawVideo() { void CCredits::DrawVideo() {
if (x28_) { /* Render movie */
/* Render movie */ if (x28_ && x28_->DrawVideo() && (x5c_27_ || x5c_28_)) {
x28_->Draw(); float alpha = x58_ / g_tweakGui->x310_;
if (x5c_27_ || x5c_28_) { if (x5c_27_) {
float alpha = x58_ / g_tweakGui->x310_; alpha = 1.f - alpha;
if (x5c_27_) {
alpha = 1.f - alpha;
}
alpha = zeus::clamp(0.f, alpha, 1.f);
zeus::CColor filterCol = zeus::skBlack;
filterCol.a() = alpha;
CCameraFilterPass::DrawFilter(EFilterType::Blend, EFilterShape::Fullscreen, filterCol, nullptr, 1.f);
} }
alpha = zeus::clamp(0.f, alpha, 1.f);
zeus::CColor filterCol = zeus::skBlack;
filterCol.a() = alpha;
CCameraFilterPass::DrawFilter(EFilterType::Blend, EFilterShape::Fullscreen, filterCol, nullptr, 1.f);
} }
} }

View File

@ -16,30 +16,26 @@ void CFaceplateDecoration::Update(float dt, CStateManager& stateMgr) {
if (xc_ready) { if (xc_ready) {
x4_tex.Unlock(); x4_tex.Unlock();
x0_id = txtrId; x0_id = txtrId;
if (m_texFilter)
m_texFilter = std::nullopt;
} }
} }
if (x0_id != txtrId && txtrId.IsValid()) { if (x0_id != txtrId && txtrId.IsValid()) {
if (m_texFilter)
m_texFilter = std::nullopt;
x0_id = txtrId; x0_id = txtrId;
x4_tex = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), txtrId}); x4_tex = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), txtrId});
xc_ready = true; xc_ready = true;
x4_tex.Lock(); x4_tex.Lock();
} }
if (!m_texFilter && x4_tex.IsLoaded())
m_texFilter.emplace(EFilterType::Blend, x4_tex);
} }
void CFaceplateDecoration::Draw(CStateManager& stateMgr) { void CFaceplateDecoration::Draw(CStateManager& stateMgr) {
if (xc_ready && m_texFilter) { if (xc_ready && x4_tex) {
SCOPED_GRAPHICS_DEBUG_GROUP("CFaceplateDecoration::Draw", zeus::skPurple); SCOPED_GRAPHICS_DEBUG_GROUP("CFaceplateDecoration::Draw", zeus::skPurple);
zeus::CColor color = zeus::skWhite; float alpha = stateMgr.GetPlayer().GetVisorSteam().GetAlpha();
color.a() = stateMgr.GetPlayer().GetVisorSteam().GetAlpha(); if (!zeus::close_enough(alpha, 0.f)) {
m_texFilter->DrawFilter(EFilterShape::FullscreenQuarters, color, 1.f); zeus::CColor color = zeus::skWhite;
color.a() = alpha;
CCameraFilterPass::DrawFilter(EFilterType::Blend, EFilterShape::FullscreenQuarters, color, x4_tex.GetObj(), 1.f);
}
} }
} }

View File

@ -4,7 +4,7 @@
#include "Runtime/CToken.hpp" #include "Runtime/CToken.hpp"
#include "Runtime/RetroTypes.hpp" #include "Runtime/RetroTypes.hpp"
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp" #include "Runtime/Graphics/CTexture.hpp"
namespace metaforce { namespace metaforce {
class CStateManager; class CStateManager;
@ -15,7 +15,6 @@ class CFaceplateDecoration {
CAssetId x0_id; CAssetId x0_id;
TToken<CTexture> x4_tex; TToken<CTexture> x4_tex;
bool xc_ready = false; bool xc_ready = false;
std::optional<CTexturedQuadFilter> m_texFilter;
public: public:
explicit CFaceplateDecoration(CStateManager& stateMgr); explicit CFaceplateDecoration(CStateManager& stateMgr);

View File

@ -1805,7 +1805,7 @@ void CFrontEndUI::Draw() {
} else { } else {
if ((xcc_curMoviePtr != nullptr)) { if ((xcc_curMoviePtr != nullptr)) {
/* Render movie */ /* Render movie */
xcc_curMoviePtr->Draw(); xcc_curMoviePtr->DrawVideo();
} }
if (x50_curScreen == EScreen::FileSelect && x54_nextScreen == EScreen::FileSelect) { if (x50_curScreen == EScreen::FileSelect && x54_nextScreen == EScreen::FileSelect) {

View File

@ -11,8 +11,6 @@
#include "Runtime/Audio/CSfxManager.hpp" #include "Runtime/Audio/CSfxManager.hpp"
#include "Runtime/Audio/CStaticAudioPlayer.hpp" #include "Runtime/Audio/CStaticAudioPlayer.hpp"
#include "Runtime/Camera/CCameraFilter.hpp" #include "Runtime/Camera/CCameraFilter.hpp"
#include "Runtime/Graphics/Shaders/CColoredQuadFilter.hpp"
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp"
#include "Runtime/GuiSys/CGuiTextSupport.hpp" #include "Runtime/GuiSys/CGuiTextSupport.hpp"
#include "Runtime/Input/CRumbleGenerator.hpp" #include "Runtime/Input/CRumbleGenerator.hpp"
#include "Runtime/MP1/CGBASupport.hpp" #include "Runtime/MP1/CGBASupport.hpp"

View File

@ -601,6 +601,7 @@ void CInGameGuiManager::Draw(CStateManager& stateMgr) {
float z = 0.5f * (zT * zT * zT * zT * zT * (CGraphics::GetViewportHeight() - 12.f) + 12.f); float z = 0.5f * (zT * zT * zT * zT * zT * (CGraphics::GetViewportHeight() - 12.f) + 12.f);
float x = 0.5f * (xT * (CGraphics::GetViewportWidth() - 12.f) + 12.f); float x = 0.5f * (xT * (CGraphics::GetViewportWidth() - 12.f) + 12.f);
// TODO
// const std::array<CTexturedQuadFilter::Vert, 4> verts{{ // const std::array<CTexturedQuadFilter::Vert, 4> verts{{
// {{-x, 0.f, z}, {0.f, 0.f}}, // {{-x, 0.f, z}, {0.f, 0.f}},
// {{-x, 0.f, -z}, {0.f, 1.f}}, // {{-x, 0.f, -z}, {0.f, 1.f}},

View File

@ -214,7 +214,8 @@ void CMFGame::Draw() {
if (x1c_flowState == EGameFlowState::CinematicSkip) { if (x1c_flowState == EGameFlowState::CinematicSkip) {
const float c = std::min(1.f, 1.f - x20_cineSkipTime); const float c = std::min(1.f, 1.f - x20_cineSkipTime);
m_fadeToBlack.draw(zeus::CColor{c, c, c, c}); CCameraFilterPass::DrawFilter(EFilterType::Multiply, EFilterShape::Fullscreen, zeus::CColor{c, c, c, c}, nullptr,
1.f);
} }
} }

View File

@ -5,7 +5,6 @@
#include "Runtime/CMFGameBase.hpp" #include "Runtime/CMFGameBase.hpp"
#include "Runtime/Camera/CCameraFilter.hpp" #include "Runtime/Camera/CCameraFilter.hpp"
#include "Runtime/Graphics/Shaders/CColoredQuadFilter.hpp"
#include "Runtime/MP1/CInGameGuiManager.hpp" #include "Runtime/MP1/CInGameGuiManager.hpp"
namespace metaforce { namespace metaforce {
@ -26,8 +25,6 @@ class CMFGame : public CMFGameBase {
bool x2a_24_initialized : 1 = false; bool x2a_24_initialized : 1 = false;
bool x2a_25_samusAlive : 1 = true; bool x2a_25_samusAlive : 1 = true;
CColoredQuadFilter m_fadeToBlack{EFilterType::Multiply};
bool IsCameraActiveFlow() const { bool IsCameraActiveFlow() const {
return (x1c_flowState == EGameFlowState::InGame || x1c_flowState == EGameFlowState::SamusDied); return (x1c_flowState == EGameFlowState::InGame || x1c_flowState == EGameFlowState::SamusDied);
} }

View File

@ -85,12 +85,15 @@ void CPauseScreenBlur::Update(float dt, const CStateManager& stateMgr, bool b) {
void CPauseScreenBlur::Draw(const CStateManager&) { void CPauseScreenBlur::Draw(const CStateManager&) {
SCOPED_GRAPHICS_DEBUG_GROUP("CPauseScreenBlur::Draw", zeus::skPurple); SCOPED_GRAPHICS_DEBUG_GROUP("CPauseScreenBlur::Draw", zeus::skPurple);
x1c_camBlur.Draw(true); x1c_camBlur.Draw(true);
CGraphics::DisableAllLights();
CGraphics::SetAmbientColor(zeus::skWhite);
const float t = std::fabs(x18_blurAmt); const float t = std::fabs(x18_blurAmt);
if (x1c_camBlur.GetCurrType() != EBlurType::NoBlur) { if (x1c_camBlur.GetCurrType() != EBlurType::NoBlur) {
const auto filterColor = zeus::CColor::lerp(zeus::skWhite, g_tweakGuiColors->GetPauseBlurFilterColor(), t); const auto filterColor = zeus::CColor::lerp(zeus::skWhite, g_tweakGuiColors->GetPauseBlurFilterColor(), t);
m_quarterFilter.DrawFilter(EFilterShape::FullscreenQuarters, filterColor, t); CCameraFilterPass::DrawFilter(EFilterType::Multiply, EFilterShape::FullscreenQuarters, filterColor,
x4_mapLightQuarter.GetObj(), t);
const auto scanLinesColor = zeus::CColor::lerp(zeus::skWhite, zeus::CColor(0.75f, 1.f), t); const auto scanLinesColor = zeus::CColor::lerp(zeus::skWhite, zeus::CColor(0.75f, 1.f), t);
m_linesFilter.draw(scanLinesColor); CCameraFilterPass::DrawFilter(EFilterType::Multiply, EFilterShape::ScanLinesEven, scanLinesColor, nullptr, t);
} }
if (x50_24_blurring /*&& x1c_camBlur.x2d_noPersistentCopy*/) { if (x50_24_blurring /*&& x1c_camBlur.x2d_noPersistentCopy*/) {

View File

@ -3,8 +3,6 @@
#include "Runtime/CToken.hpp" #include "Runtime/CToken.hpp"
#include "Runtime/Camera/CCameraFilter.hpp" #include "Runtime/Camera/CCameraFilter.hpp"
#include "Runtime/Graphics/CTexture.hpp" #include "Runtime/Graphics/CTexture.hpp"
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp"
#include "Runtime/Graphics/Shaders/CScanLinesFilter.hpp"
#include "Runtime/MP1/CInGameGuiManagerCommon.hpp" #include "Runtime/MP1/CInGameGuiManagerCommon.hpp"
namespace metaforce { namespace metaforce {
@ -23,9 +21,6 @@ class CPauseScreenBlur {
bool x50_24_blurring : 1 = false; bool x50_24_blurring : 1 = false;
bool x50_25_gameDraw : 1 = true; bool x50_25_gameDraw : 1 = true;
CTexturedQuadFilter m_quarterFilter{EFilterType::Multiply, x4_mapLightQuarter};
CScanLinesFilterEven m_linesFilter{EFilterType::Multiply};
void OnBlurComplete(bool); void OnBlurComplete(bool);
void SetState(EState state); void SetState(EState state);

View File

@ -4,9 +4,10 @@
namespace metaforce::MP1 { namespace metaforce::MP1 {
const char* kMovies[] = {"Video/wingame.thp", "Video/wingame_good.thp", "Video/wingame_best.thp", const char* kMovies[] = {
"Video/losegame.thp", "Video/05_tallonText.thp", "Video/AfterCredits.thp", "Video/wingame.thp", "Video/wingame_good.thp", "Video/wingame_best.thp", "Video/losegame.thp",
"Video/SpecialEnding.thp", "Video/creditBG.thp"}; "Video/05_tallonText.thp", "Video/AfterCredits.thp", "Video/SpecialEnding.thp", "Video/creditBG.thp",
};
bool CPlayMovie::IsResultsScreen(EWhichMovie which) { return int(which) <= 2; } bool CPlayMovie::IsResultsScreen(EWhichMovie which) { return int(which) <= 2; }
@ -15,6 +16,7 @@ CPlayMovie::CPlayMovie(EWhichMovie which) : CIOWin("CPlayMovie"), x18_which(whic
CIOWin::EMessageReturn CPlayMovie::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { CIOWin::EMessageReturn CPlayMovie::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) {
return EMessageReturn::RemoveIOWinAndExit; return EMessageReturn::RemoveIOWinAndExit;
} }
void CPlayMovie::Draw() { void CPlayMovie::Draw() {
if (x14_ != 3) { if (x14_ != 3) {
return; return;
@ -28,7 +30,14 @@ void CPlayMovie::Draw() {
} }
} }
void CPlayMovie::DrawVideo() {} void CPlayMovie::DrawVideo() {
void CPlayMovie::DrawText() {} if (x38_moviePlayer) {
x38_moviePlayer->DrawVideo();
}
}
void CPlayMovie::DrawText() {
// TODO
}
} // namespace metaforce::MP1 } // namespace metaforce::MP1

View File

@ -355,9 +355,6 @@ void CPlayerVisor::DrawScanEffect(const CStateManager& mgr, CTargetingManager* t
rect.x10_height = int(vpH); rect.x10_height = int(vpH);
CGraphics::ResolveSpareTexture(rect, 0, GX::TF_RGB565); CGraphics::ResolveSpareTexture(rect, 0, GX::TF_RGB565);
// TODO hack; figure out why needed
CGraphics::SetCullMode(ERglCullMode::None);
{ {
SCOPED_GRAPHICS_DEBUG_GROUP("x64_scanDim Draw", zeus::skMagenta); SCOPED_GRAPHICS_DEBUG_GROUP("x64_scanDim Draw", zeus::skMagenta);
x64_scanDim.Draw(); x64_scanDim.Draw();

View File

@ -4,8 +4,6 @@
#include "Runtime/CPlayerState.hpp" #include "Runtime/CPlayerState.hpp"
#include "Runtime/Camera/CCameraFilter.hpp" #include "Runtime/Camera/CCameraFilter.hpp"
#include "Runtime/Graphics/CModel.hpp" #include "Runtime/Graphics/CModel.hpp"
#include "Runtime/Graphics/Shaders/CColoredQuadFilter.hpp"
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp"
#include "Runtime/RetroTypes.hpp" #include "Runtime/RetroTypes.hpp"
#include "Runtime/rstl.hpp" #include "Runtime/rstl.hpp"

View File

@ -86,7 +86,7 @@ EQuitAction CQuitGameScreen::Update(float dt) {
void CQuitGameScreen::Draw() { void CQuitGameScreen::Draw() {
SCOPED_GRAPHICS_DEBUG_GROUP("CQuitGameScreen::Draw", zeus::skPurple); SCOPED_GRAPHICS_DEBUG_GROUP("CQuitGameScreen::Draw", zeus::skPurple);
if (x0_type == EQuitType::QuitGame) { if (x0_type == EQuitType::QuitGame) {
m_blackScreen->draw(zeus::CColor(0.f, 0.5f)); CCameraFilterPass::DrawFilter(EFilterType::Blend, EFilterShape::Fullscreen, zeus::CColor{0.f, 0.5f}, nullptr, 1.f);
} }
if (x10_loadedFrame) { if (x10_loadedFrame) {
@ -111,10 +111,6 @@ void CQuitGameScreen::ProcessUserInput(const CFinalInput& input) {
} }
} }
CQuitGameScreen::CQuitGameScreen(EQuitType tp) : x0_type(tp) { CQuitGameScreen::CQuitGameScreen(EQuitType tp) : x0_type(tp) { x4_frame = g_SimplePool->GetObj("FRME_QuitScreen"); }
x4_frame = g_SimplePool->GetObj("FRME_QuitScreen");
if (tp == EQuitType::QuitGame)
m_blackScreen.emplace(EFilterType::Blend);
}
} // namespace metaforce::MP1 } // namespace metaforce::MP1

View File

@ -4,7 +4,6 @@
#include "Runtime/CToken.hpp" #include "Runtime/CToken.hpp"
#include "Runtime/RetroTypes.hpp" #include "Runtime/RetroTypes.hpp"
#include "Runtime/Graphics/Shaders/CColoredQuadFilter.hpp"
#include "Runtime/GuiSys/CGuiFrame.hpp" #include "Runtime/GuiSys/CGuiFrame.hpp"
namespace metaforce { namespace metaforce {
@ -25,7 +24,7 @@ class CQuitGameScreen {
CGuiFrame* x10_loadedFrame = nullptr; CGuiFrame* x10_loadedFrame = nullptr;
CGuiTableGroup* x14_tablegroup_quitgame = nullptr; CGuiTableGroup* x14_tablegroup_quitgame = nullptr;
EQuitAction x18_action = EQuitAction::None; EQuitAction x18_action = EQuitAction::None;
std::optional<CColoredQuadFilter> m_blackScreen;
void SetColors(); void SetColors();
public: public:

View File

@ -12,6 +12,7 @@
#include "Runtime/World/CGameLight.hpp" #include "Runtime/World/CGameLight.hpp"
#include "Runtime/World/CPlayer.hpp" #include "Runtime/World/CPlayer.hpp"
#include "Runtime/World/CScriptTrigger.hpp" #include "Runtime/World/CScriptTrigger.hpp"
#include "Runtime/Graphics/CCubeRenderer.hpp"
#include "TCastTo.hpp" // Generated file, do not modify include path #include "TCastTo.hpp" // Generated file, do not modify include path
@ -23,8 +24,7 @@ CSamusHud::CSamusHud(CStateManager& stateMgr)
: x8_targetingMgr(stateMgr) : x8_targetingMgr(stateMgr)
, x258_frmeHelmet(g_SimplePool->GetObj("FRME_Helmet")) , x258_frmeHelmet(g_SimplePool->GetObj("FRME_Helmet"))
, x268_frmeBaseHud(g_SimplePool->GetObj("FRME_BaseHud")) , x268_frmeBaseHud(g_SimplePool->GetObj("FRME_BaseHud"))
, x2e0_27_energyLow(stateMgr.GetPlayer().IsEnergyLow(stateMgr)) , x2e0_27_energyLow(stateMgr.GetPlayer().IsEnergyLow(stateMgr)) {
, m_energyDrainFilter(g_tweakGui->GetEnergyDrainFilterAdditive() ? EFilterType::Add : EFilterType::Blend) {
x33c_lights = std::make_unique<CActorLights>(8, zeus::skZero3f, 4, 1, true, 0, 0, 0.1f); x33c_lights = std::make_unique<CActorLights>(8, zeus::skZero3f, 4, 1, true, 0, 0, 0.1f);
x340_hudLights.resize(3, SCachedHudLight(zeus::skZero3f, zeus::skWhite, 0.f, 0.f, 0.f, 0.f)); x340_hudLights.resize(3, SCachedHudLight(zeus::skZero3f, zeus::skWhite, 0.f, 0.f, 0.f, 0.f));
x46c_.resize(3); x46c_.resize(3);
@ -1387,7 +1387,8 @@ void CSamusHud::DrawAttachedEnemyEffect(const CStateManager& mgr) {
zeus::CColor filterColor = g_tweakGuiColors->GetEnergyDrainFilterColor(); zeus::CColor filterColor = g_tweakGuiColors->GetEnergyDrainFilterColor();
filterColor.a() *= alpha; filterColor.a() *= alpha;
m_energyDrainFilter.draw(filterColor); EFilterType filterType = g_tweakGui->GetEnergyDrainFilterAdditive() ? EFilterType::Add : EFilterType::Blend;
CCameraFilterPass::DrawFilter(filterType, EFilterShape::Fullscreen, filterColor, nullptr, 1.f);
} }
void CSamusHud::Draw(const CStateManager& mgr, float alpha, CInGameGuiManager::EHelmetVisMode helmetVis, bool hudVis, void CSamusHud::Draw(const CStateManager& mgr, float alpha, CInGameGuiManager::EHelmetVisMode helmetVis, bool hudVis,
@ -1408,7 +1409,8 @@ void CSamusHud::Draw(const CStateManager& mgr, float alpha, CInGameGuiManager::E
if (helmetVis != CInGameGuiManager::EHelmetVisMode::ReducedUpdate && if (helmetVis != CInGameGuiManager::EHelmetVisMode::ReducedUpdate &&
helmetVis < CInGameGuiManager::EHelmetVisMode::HelmetOnly) { helmetVis < CInGameGuiManager::EHelmetVisMode::HelmetOnly) {
if (alpha < 1.f) { if (alpha < 1.f) {
m_cookieCutterStatic.draw(zeus::skWhite, 1.f - alpha); CCameraFilterPass::DrawFilter(EFilterType::NoColor, EFilterShape::CookieCutterDepthRandomStatic, zeus::skWhite,
nullptr, 1.f - alpha);
} }
if (x288_loadedSelectedHud) { if (x288_loadedSelectedHud) {
@ -1447,8 +1449,10 @@ void CSamusHud::Draw(const CStateManager& mgr, float alpha, CInGameGuiManager::E
} }
x2ac_radarIntf->Draw(mgr, t * alpha); x2ac_radarIntf->Draw(mgr, t * alpha);
} }
// Depth read/write enable g_Renderer->SetDepthReadWrite(true, true);
} }
// TODO timer stuff?
} }
void CSamusHud::DrawHelmet(const CStateManager& mgr, float camYOff) { void CSamusHud::DrawHelmet(const CStateManager& mgr, float camYOff) {

View File

@ -166,9 +166,6 @@ class CSamusHud {
std::array<float, 32> x72c_camZTweaks; std::array<float, 32> x72c_camZTweaks;
rstl::reserved_vector<SProfileInfo, 15> x7ac_; rstl::reserved_vector<SProfileInfo, 15> x7ac_;
CColoredQuadFilter m_energyDrainFilter;
CCookieCutterDepthRandomStaticFilter m_cookieCutterStatic{EFilterType::NoColor};
static CSamusHud* g_SamusHud; static CSamusHud* g_SamusHud;
static rstl::reserved_vector<bool, 4> BuildPlayerHasVisors(const CStateManager& mgr); static rstl::reserved_vector<bool, 4> BuildPlayerHasVisors(const CStateManager& mgr);
static rstl::reserved_vector<bool, 4> BuildPlayerHasBeams(const CStateManager& mgr); static rstl::reserved_vector<bool, 4> BuildPlayerHasBeams(const CStateManager& mgr);

View File

@ -120,15 +120,16 @@ CIOWin::EMessageReturn CSlideShow::OnMessage(const CArchitectureMessage& msg, CA
} }
void CSlideShow::SSlideData::Draw() { void CSlideShow::SSlideData::Draw() {
if (!IsLoaded()) { // TODO
return; // if (!IsLoaded()) {
} // return;
// }
const zeus::CRectangle rect; //
m_texQuad->draw(x30_mulColor, 1.f, rect); // const zeus::CRectangle rect;
// m_texQuad->draw(x30_mulColor, 1.f, rect);
const zeus::CVector2f centeredOffset((x28_canvasSize.x() - m_texQuad->GetTex()->GetWidth()) * 0.5f, //
(x28_canvasSize.y() - m_texQuad->GetTex()->GetHeight()) * 0.5f); // const zeus::CVector2f centeredOffset((x28_canvasSize.x() - m_texQuad->GetTex()->GetWidth()) * 0.5f,
// (x28_canvasSize.y() - m_texQuad->GetTex()->GetHeight()) * 0.5f);
} }
void CSlideShow::Draw() { void CSlideShow::Draw() {

View File

@ -10,7 +10,6 @@
#include "Runtime/RetroTypes.hpp" #include "Runtime/RetroTypes.hpp"
#include "Runtime/Audio/CSfxManager.hpp" #include "Runtime/Audio/CSfxManager.hpp"
#include "Runtime/Camera/CCameraFilter.hpp" #include "Runtime/Camera/CCameraFilter.hpp"
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp"
#include "Runtime/GuiSys/CGuiTextSupport.hpp" #include "Runtime/GuiSys/CGuiTextSupport.hpp"
#include <zeus/CColor.hpp> #include <zeus/CColor.hpp>
@ -27,7 +26,6 @@ public:
u32 x4_ = -1; u32 x4_ = -1;
u32 x8_ = -1; u32 x8_ = -1;
std::optional<CTexturedQuadFilterAlpha> m_texQuad;
zeus::CVector2f x18_vpOffset; zeus::CVector2f x18_vpOffset;
zeus::CVector2f x20_vpSize; zeus::CVector2f x20_vpSize;
zeus::CVector2f x28_canvasSize; zeus::CVector2f x28_canvasSize;
@ -35,8 +33,6 @@ public:
explicit SSlideData(CSlideShow& parent) : x0_parent(parent) { x30_mulColor.a() = 0.f; } explicit SSlideData(CSlideShow& parent) : x0_parent(parent) { x30_mulColor.a() = 0.f; }
void SetTexture(const TLockedToken<CTexture>& tex) { m_texQuad.emplace(EFilterType::Blend, tex); }
bool IsLoaded() const { return m_texQuad && m_texQuad->GetTex().IsLoaded(); }
void Draw(); void Draw();
}; };

View File

@ -7,6 +7,7 @@
#include "Runtime/CSimplePool.hpp" #include "Runtime/CSimplePool.hpp"
#include "Runtime/GameGlobalObjects.hpp" #include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Graphics/CCubeRenderer.hpp" #include "Runtime/Graphics/CCubeRenderer.hpp"
#include "Runtime/Graphics/CGX.hpp"
#include "Runtime/Weapon/CGameProjectile.hpp" #include "Runtime/Weapon/CGameProjectile.hpp"
#include "Runtime/World/CPlayer.hpp" #include "Runtime/World/CPlayer.hpp"
#include "Runtime/World/CScriptEffect.hpp" #include "Runtime/World/CScriptEffect.hpp"
@ -42,9 +43,7 @@ COmegaPirate::CFlash::CFlash(TUniqueId uid, const CEntityInfo& info, const zeus:
TLockedToken<CTexture>& thermalSpot, float delay) TLockedToken<CTexture>& thermalSpot, float delay)
: CActor(uid, true, "Omega Pirate Flash", info, zeus::CTransform::Translate(pos), CModelData::CModelDataNull(), {}, : CActor(uid, true, "Omega Pirate Flash", info, zeus::CTransform::Translate(pos), CModelData::CModelDataNull(), {},
CActorParameters::None(), kInvalidUniqueId) CActorParameters::None(), kInvalidUniqueId)
, xf4_delay(delay) , xf4_delay(delay) {}
, m_thermalSpotAdd(EFilterType::Add, thermalSpot)
, m_thermalSpotSubtract(EFilterType::Subtract, thermalSpot) {}
void COmegaPirate::CFlash::Accept(IVisitor& visitor) { visitor.Visit(this); } void COmegaPirate::CFlash::Accept(IVisitor& visitor) { visitor.Visit(this); }
@ -77,9 +76,9 @@ void COmegaPirate::CFlash::Think(float dt, CStateManager& mgr) {
void COmegaPirate::CFlash::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { void COmegaPirate::CFlash::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) {
mgr.RenderLast(GetUniqueId()); mgr.RenderLast(GetUniqueId());
// if (xf0_thermalSpot == nullptr && xe8_thermalSpotToken.IsLocked() && xe8_thermalSpotToken.HasReference()) { if (xf0_thermalSpot == nullptr && xe8_thermalSpotToken.IsLocked() && xe8_thermalSpotToken.HasReference()) {
// xf0_thermalSpot = xe8_thermalSpotToken.GetObj(); xf0_thermalSpot = xe8_thermalSpotToken.GetObj();
// } }
} }
void COmegaPirate::CFlash::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) {} void COmegaPirate::CFlash::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) {}
@ -89,18 +88,17 @@ void COmegaPirate::CFlash::Render(CStateManager& mgr) {
if (visor == CPlayerState::EPlayerVisor::Thermal) { if (visor == CPlayerState::EPlayerVisor::Thermal) {
return; return;
} }
if (xf0_thermalSpot == nullptr || !xe8_thermalSpotToken) {
return;
}
xf0_thermalSpot->Load(GX::TEXMAP0, EClampMode::Repeat);
float sizeMul = 35.f; float sizeMul = 35.f;
CTexturedQuadFilter* filter = nullptr;
if (visor == CPlayerState::EPlayerVisor::XRay) { if (visor == CPlayerState::EPlayerVisor::XRay) {
// CGraphics::SetBlendMode(ERglBlendMode::Subtract, ERglBlendFactor::One, ERglBlendFactor::Zero, CGX::SetBlendMode(GX::BM_SUBTRACT, GX::BL_ONE, GX::BL_ZERO, GX::LO_CLEAR);
// ERglLogicOp::Clear);
filter = &m_thermalSpotSubtract;
sizeMul = 60.f; sizeMul = 60.f;
} else { } else {
// CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear);
// ERglLogicOp::Clear);
filter = &m_thermalSpotAdd;
} }
float size = xfc_size * sizeMul; float size = xfc_size * sizeMul;
@ -109,13 +107,20 @@ void COmegaPirate::CFlash::Render(CStateManager& mgr) {
const auto rvS = GetTranslation() - rightVec; const auto rvS = GetTranslation() - rightVec;
const auto rvP = GetTranslation() + rightVec; const auto rvP = GetTranslation() + rightVec;
CGraphics::SetModelMatrix(zeus::CTransform()); CGraphics::SetModelMatrix(zeus::CTransform());
const std::array<CTexturedQuadFilter::Vert, 4> verts{{ CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc);
{rvS + upVec, {0.f, 0.f}}, CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
{rvP + upVec, {0.f, 1.f}}, CGraphics::SetDepthWriteMode(false, ERglEnum::Always, false);
{rvS - upVec, {1.f, 0.f}}, CGraphics::StreamColor(zeus::CColor{1.f, std::min(1.f, size)});
{rvP - upVec, {1.f, 1.f}}, CGraphics::StreamBegin(GX::TRIANGLEFAN);
}}; CGraphics::StreamTexcoord(0.f, 0.f);
filter->drawVerts(zeus::CColor{1.f, std::min(1.f, size)}, verts); CGraphics::StreamVertex(rvS + upVec);
CGraphics::StreamTexcoord(1.f, 0.f);
CGraphics::StreamVertex(rvP + upVec);
CGraphics::StreamTexcoord(1.f, 1.f);
CGraphics::StreamVertex(rvP - upVec);
CGraphics::StreamTexcoord(0.f, 1.f);
CGraphics::StreamVertex(rvS - upVec);
CGraphics::StreamEnd();
} }
COmegaPirate::COmegaPirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, COmegaPirate::COmegaPirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,

View File

@ -7,15 +7,12 @@ class COmegaPirate : public CElitePirate {
private: private:
class CFlash : public CActor { class CFlash : public CActor {
private: private:
// TToken<CTexture> xe8_thermalSpotToken; TToken<CTexture> xe8_thermalSpotToken;
// CTexture* xf0_thermalSpot = nullptr; CTexture* xf0_thermalSpot = nullptr;
float xf4_delay; float xf4_delay;
float xf8_time = 0.f; float xf8_time = 0.f;
float xfc_size = 0.f; float xfc_size = 0.f;
CTexturedQuadFilter m_thermalSpotAdd;
CTexturedQuadFilter m_thermalSpotSubtract;
public: public:
DEFINE_ENTITY DEFINE_ENTITY
CFlash(TUniqueId uid, const CEntityInfo& info, const zeus::CVector3f& pos, TLockedToken<CTexture>& thermalSpot, CFlash(TUniqueId uid, const CEntityInfo& info, const zeus::CVector3f& pos, TLockedToken<CTexture>& thermalSpot,

View File

@ -1386,44 +1386,29 @@ void CThardus::RenderFlare(const CStateManager& mgr, float t) {
if (!x91c_flareTexture) { if (!x91c_flareTexture) {
return; return;
} }
x91c_flareTexture->Load(GX::TEXMAP0, EClampMode::Repeat);
if (!m_flareFilter) {
m_flareFilter.emplace(EFilterType::Add, x91c_flareTexture);
}
const float scale = 30.f * t; const float scale = 30.f * t;
zeus::CVector3f offset = scale * CGraphics::g_ViewMatrix.basis[2]; zeus::CVector3f offset = scale * CGraphics::g_ViewMatrix.basis[2];
zeus::CVector3f max = x92c_currentRockPos + (scale * CGraphics::g_ViewMatrix.basis[0]); zeus::CVector3f max = x92c_currentRockPos + (scale * CGraphics::g_ViewMatrix.basis[0]);
zeus::CVector3f min = x92c_currentRockPos - (scale * CGraphics::g_ViewMatrix.basis[0]); zeus::CVector3f min = x92c_currentRockPos - (scale * CGraphics::g_ViewMatrix.basis[0]);
CGraphics::SetModelMatrix(zeus::CTransform()); CGraphics::SetModelMatrix({});
const std::array<CTexturedQuadFilter::Vert, 4> verts{{
{{max.x() + offset.x(), max.y() + offset.y(), max.z() + offset.z()}, {0.f, 1.f}},
{{min.x() + offset.x(), min.y() + offset.y(), min.z() + offset.z()}, {0.f, 0.f}},
{{max.x() - offset.x(), max.y() - offset.y(), max.z() - offset.z()}, {1.f, 1.f}},
{{min.x() - offset.x(), min.y() - offset.y(), min.z() - offset.z()}, {1.f, 0.f}},
}};
m_flareFilter->drawVerts({t, t}, verts);
}
#if 0
CGraphics::SetModelMatrix(zeus::CTransform());
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear); CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear);
CGraphics::SetTevOp(0, CGraphics::sTevPass805a5ebc); CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc);
CGraphics::SetTevOp(1, CGraphics::skPassThru); CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
CGraphics::SetDepthWriteMode(false, ERglEnum::Always, false); CGraphics::SetDepthWriteMode(false, ERglEnum::Always, false);
CGraphics::StreamColor(zeus::CColor(f1, f1)); CGraphics::StreamColor({t, t});
CGraphics::StreamBegin(0xa0); CGraphics::StreamBegin(GX::TRIANGLEFAN);
CGraphics::StreamTexCoord(0.f, 0.f); CGraphics::StreamTexcoord(0.f, 0.f);
CGraphics::StreamVertex(min + offset); CGraphics::StreamVertex(min + offset);
CGraphics::StreamTexCoord(1.f, 0.f); CGraphics::StreamTexcoord(1.f, 0.f);
CGraphics::StreamVertex(min - offset); CGraphics::StreamVertex(min - offset);
CGraphics::StreamTexCoord(1.f, 1.f); CGraphics::StreamTexcoord(1.f, 1.f);
CGraphics::StreamVertex(max - offset); CGraphics::StreamVertex(max - offset);
CGraphics::StreamTexCoord(0.f, 1.f); CGraphics::StreamTexcoord(0.f, 1.f);
CGraphics::StreamVertex(max + offset); CGraphics::StreamVertex(max + offset);
CGraphics::StreamEnd(); CGraphics::StreamEnd();
#endif }
zeus::CVector3f CThardus::sub801de550(CStateManager& mgr) { zeus::CVector3f CThardus::sub801de550(CStateManager& mgr) {

View File

@ -171,8 +171,6 @@ class CThardus : public CPatterned {
zeus::CVector2f GetTargetVector(float arg, CStateManager& mgr); zeus::CVector2f GetTargetVector(float arg, CStateManager& mgr);
void sub801dbc40(); void sub801dbc40();
std::optional<CTexturedQuadFilter> m_flareFilter;
void DoDoubleSnap(CStateManager& mgr) { void DoDoubleSnap(CStateManager& mgr) {
x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "DoubleSnap"sv); x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "DoubleSnap"sv);
} }

View File

@ -175,8 +175,6 @@ CPlayerGun::CPlayerGun(TUniqueId playerId)
x550_camBob.SetPlayerVelocity(zeus::skZero3f); x550_camBob.SetPlayerVelocity(zeus::skZero3f);
x550_camBob.SetBobMagnitude(0.f); x550_camBob.SetBobMagnitude(0.f);
x550_camBob.SetBobTimeScale(0.f); x550_camBob.SetBobTimeScale(0.f);
m_aaboxShader.setAABB(x6c8_hologramClipCube);
} }
void CPlayerGun::InitBeamData() { void CPlayerGun::InitBeamData() {
@ -2140,13 +2138,17 @@ void CPlayerGun::DrawScreenTex(float z) {
// Use CopyScreenTex rendering to draw over framebuffer pixels in front of `z` // Use CopyScreenTex rendering to draw over framebuffer pixels in front of `z`
// This is accomplished using orthographic projection quad with sweeping `y` coordinates // This is accomplished using orthographic projection quad with sweeping `y` coordinates
// Depth is set to GEQUAL to obscure pixels in front rather than behind // Depth is set to GEQUAL to obscure pixels in front rather than behind
// m_screenQuad.draw(zeus::skWhite, 1.f, CTexturedQuadFilter::DefaultRect, z);
// TODO
// m_screenQuad.draw(zeus::skWhite, 1.f, CTexturedQuadFilter::DefaultRect, z);
} }
void CPlayerGun::DrawClipCube(const zeus::CAABox& aabb) { void CPlayerGun::DrawClipCube(const zeus::CAABox& aabb) {
// Render AABB as completely transparent object, only modifying Z-buffer // Render AABB as completely transparent object, only modifying Z-buffer
// AABB has already been set in constructor (since it's constant) // AABB has already been set in constructor (since it's constant)
m_aaboxShader.draw(zeus::skClear);
// TODO
// m_aaboxShader.draw(zeus::skClear);
} }
void CPlayerGun::Render(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) { void CPlayerGun::Render(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) {

View File

@ -10,8 +10,6 @@
#include "Runtime/Character/CActorLights.hpp" #include "Runtime/Character/CActorLights.hpp"
#include "Runtime/Character/CModelData.hpp" #include "Runtime/Character/CModelData.hpp"
#include "Runtime/Graphics/CRainSplashGenerator.hpp" #include "Runtime/Graphics/CRainSplashGenerator.hpp"
#include "Runtime/Graphics/Shaders/CAABoxShader.hpp"
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp"
#include "Runtime/Particle/CElementGen.hpp" #include "Runtime/Particle/CElementGen.hpp"
#include "Runtime/Weapon/CAuxWeapon.hpp" #include "Runtime/Weapon/CAuxWeapon.hpp"
#include "Runtime/Weapon/CFidget.hpp" #include "Runtime/Weapon/CFidget.hpp"
@ -255,10 +253,6 @@ private:
bool x835_30_inPhazonPool : 1 = false; bool x835_30_inPhazonPool : 1 = false;
bool x835_31_actorAttached : 1 = false; bool x835_31_actorAttached : 1 = false;
// CTexturedQuadFilter m_screenQuad{EFilterType::Blend, CGraphics::g_SpareTexture.get(),
// CTexturedQuadFilter::ZTest::GEqualZWrite};
CAABoxShader m_aaboxShader{true};
void InitBeamData(); void InitBeamData();
void InitBombData(); void InitBombData();
void InitMuzzleData(); void InitMuzzleData();

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "Runtime/RetroTypes.hpp" #include "Runtime/RetroTypes.hpp"
#include "Runtime/Graphics/Shaders/CWorldShadowShader.hpp" #include "Runtime/Graphics/CTexture.hpp"
#include <zeus/CAABox.hpp> #include <zeus/CAABox.hpp>
#include <zeus/CTransform.hpp> #include <zeus/CTransform.hpp>

View File

@ -194,6 +194,7 @@ void CWorldTransManager::DrawPlatformModels(CActorLights* lights) {
} }
void CWorldTransManager::DrawAllModels(CActorLights* lights) { void CWorldTransManager::DrawAllModels(CActorLights* lights) {
// TODO this needs reimpl
DrawPlatformModels(lights); DrawPlatformModels(lights);
if (!x4_modelData->x1c_samusModelData.IsNull()) { if (!x4_modelData->x1c_samusModelData.IsNull()) {
@ -210,7 +211,6 @@ void CWorldTransManager::DrawAllModels(CActorLights* lights) {
} }
void CWorldTransManager::DrawFirstPass(CActorLights* lights) { void CWorldTransManager::DrawFirstPass(CActorLights* lights) {
// CBooModel::SetReflectionCube(m_reflectionCube[0]);
zeus::CTransform translateXf = zeus::CTransform::Translate( zeus::CTransform translateXf = zeus::CTransform::Translate(
x4_modelData->x1b4_shakeResult.x(), -3.5f * (1.f - zeus::clamp(0.f, x0_curTime / 10.f, 1.f)) - 3.5f, x4_modelData->x1b4_shakeResult.x(), -3.5f * (1.f - zeus::clamp(0.f, x0_curTime / 10.f, 1.f)) - 3.5f,
x4_modelData->x1b4_shakeResult.y() + 2.f); x4_modelData->x1b4_shakeResult.y() + 2.f);
@ -228,7 +228,6 @@ void CWorldTransManager::DrawFirstPass(CActorLights* lights) {
} }
void CWorldTransManager::DrawSecondPass(CActorLights* lights) { void CWorldTransManager::DrawSecondPass(CActorLights* lights) {
// CBooModel::SetReflectionCube(m_reflectionCube[1]);
const zeus::CVector3f& samusScale = x4_modelData->x0_samusRes.GetScale(); const zeus::CVector3f& samusScale = x4_modelData->x0_samusRes.GetScale();
zeus::CTransform translateXf = zeus::CTransform translateXf =
zeus::CTransform::Translate(-0.1f * samusScale.x(), -0.5f * samusScale.y(), 1.5f * samusScale.z()); zeus::CTransform::Translate(-0.1f * samusScale.x(), -0.5f * samusScale.y(), 1.5f * samusScale.z());
@ -243,46 +242,7 @@ void CWorldTransManager::DrawEnabled() {
CActorLights lights(0, zeus::skZero3f, 4, 4, 0, 0, 0, 0.1f); CActorLights lights(0, zeus::skZero3f, 4, 4, 0, 0, 0, 0.1f);
lights.BuildFakeLightList(x4_modelData->x1a0_lights, zeus::CColor{0.1f, 0.1f, 0.1f, 1.0f}); lights.BuildFakeLightList(x4_modelData->x1a0_lights, zeus::CColor{0.1f, 0.1f, 0.1f, 1.0f});
// if (m_reflectionCube[0]) { float wsAspect = 1.7777f; // TODO
// SViewport backupVp = g_Viewport;
// constexpr float width = CUBEMAP_RES;
// CGraphics::g_BooMainCommandQueue->setRenderTarget(m_reflectionCube[0], 0);
// g_Renderer->SetViewport(0, 0, width, width);
// g_Renderer->SetPerspective(90.f, width, width, 0.2f, 750.f);
//
// if (x0_curTime < x4_modelData->x1d4_dissolveEndTime) {
// zeus::CTransform mainCamXf =
// zeus::CTransform::RotateZ(zeus::degToRad(zeus::clamp(0.f, x0_curTime / 25.f, 100.f) * 360.f + 180.f - 90.f));
// for (int face = 0; face < 6; ++face) {
// CGraphics::g_BooMainCommandQueue->setRenderTarget(m_reflectionCube[0], face);
// CGraphics::g_BooMainCommandQueue->clearTarget();
// zeus::CTransform camXf =
// zeus::CTransform(mainCamXf.basis * CGraphics::skCubeBasisMats[face], zeus::CVector3f(0.f, 0.f, 1.5f));
// g_Renderer->SetWorldViewpoint(camXf);
// DrawPlatformModels(&lights);
// }
// CGraphics::g_BooMainCommandQueue->generateMipmaps(m_reflectionCube[0]);
// }
// if (x0_curTime > x4_modelData->x1d0_dissolveStartTime) {
// zeus::CTransform mainCamXf = zeus::CTransform::RotateZ(
// zeus::degToRad(48.f * zeus::clamp(0.f, (x0_curTime - x4_modelData->x1d0_dissolveStartTime + 2.f) / 5.f, 1.f) +
// 180.f - 24.f));
// for (int face = 0; face < 6; ++face) {
// CGraphics::g_BooMainCommandQueue->setRenderTarget(m_reflectionCube[1], face);
// CGraphics::g_BooMainCommandQueue->clearTarget();
// zeus::CTransform camXf =
// zeus::CTransform(mainCamXf.basis * CGraphics::skCubeBasisMats[face], zeus::CVector3f(0.f, 0.f, 1.5f));
// g_Renderer->SetWorldViewpoint(camXf);
// DrawPlatformModels(&lights);
// }
// CGraphics::g_BooMainCommandQueue->generateMipmaps(m_reflectionCube[1]);
// }
//
// CBooRenderer::BindMainDrawTarget();
// g_Renderer->SetViewport(backupVp.x0_left, backupVp.x4_top, backupVp.x8_width, backupVp.xc_height);
// }
float wsAspect = CWideScreenFilter::SetViewportToMatch(1.f);
g_Renderer->SetPerspective(CCameraManager::FirstPersonFOV(), wsAspect, CCameraManager::NearPlane(), g_Renderer->SetPerspective(CCameraManager::FirstPersonFOV(), wsAspect, CCameraManager::NearPlane(),
CCameraManager::FarPlane()); CCameraManager::FarPlane());
@ -402,13 +362,6 @@ void CWorldTransManager::EnableTransition(const CAnimRes& samusRes, CAssetId pla
x30_type = ETransType::Enabled; x30_type = ETransType::Enabled;
x4_modelData = std::make_unique<SModelDatas>(samusRes); x4_modelData = std::make_unique<SModelDatas>(samusRes);
// if (!m_reflectionCube[0] && hecl::com_cubemaps->toBoolean())
// CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) {
// m_reflectionCube[0] = ctx.newCubeRenderTexture(CUBEMAP_RES, CUBEMAP_MIPS);
// m_reflectionCube[1] = ctx.newCubeRenderTexture(CUBEMAP_RES, CUBEMAP_MIPS);
// return true;
// } BooTrace);
x8_textData.reset(); x8_textData.reset();
x20_random.SetSeed(99); x20_random.SetSeed(99);

View File

@ -10,9 +10,6 @@
#include "Runtime/Camera/CCameraFilter.hpp" #include "Runtime/Camera/CCameraFilter.hpp"
#include "Runtime/Character/CModelData.hpp" #include "Runtime/Character/CModelData.hpp"
#include "Runtime/Graphics/CLight.hpp" #include "Runtime/Graphics/CLight.hpp"
#include "Runtime/Graphics/Shaders/CCameraBlurFilter.hpp"
#include "Runtime/Graphics/Shaders/CColoredQuadFilter.hpp"
#include "Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp"
#include "Runtime/GuiSys/CGuiTextSupport.hpp" #include "Runtime/GuiSys/CGuiTextSupport.hpp"
#include "Runtime/GuiSys/CStringTable.hpp" #include "Runtime/GuiSys/CStringTable.hpp"

View File

@ -20,8 +20,8 @@ target_include_directories(aurora PRIVATE ../imgui ../extern/imgui)
target_link_libraries(aurora PRIVATE dawn_native dawncpp webgpu_dawn zeus logvisor SDL2-static xxhash target_link_libraries(aurora PRIVATE dawn_native dawncpp webgpu_dawn zeus logvisor SDL2-static xxhash
absl::btree absl::flat_hash_map) absl::btree absl::flat_hash_map)
if (APPLE) if (APPLE)
target_compile_definitions(aurora PRIVATE DAWN_ENABLE_BACKEND_METAL) target_compile_definitions(aurora PRIVATE DAWN_ENABLE_BACKEND_METAL DAWN_ENABLE_BACKEND_VULKAN)
target_sources(aurora PRIVATE lib/dawn/MetalBinding.mm) target_sources(aurora PRIVATE lib/dawn/MetalBinding.mm lib/dawn/VulkanBinding.cpp)
set_source_files_properties(lib/dawn/MetalBinding.mm PROPERTIES COMPILE_FLAGS -fobjc-arc) set_source_files_properties(lib/dawn/MetalBinding.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
elseif (WIN32) elseif (WIN32)
target_compile_definitions(aurora PRIVATE target_compile_definitions(aurora PRIVATE

View File

@ -30,6 +30,7 @@ struct Vec3 {
constexpr Vec3() = default; constexpr Vec3() = default;
constexpr Vec3(T x, T y, T z) : x(x), y(y), z(z) {} constexpr Vec3(T x, T y, T z) : x(x), y(y), z(z) {}
constexpr Vec3(const zeus::CVector3f& vec) : x(vec.x()), y(vec.y()), z(vec.z()) {} constexpr Vec3(const zeus::CVector3f& vec) : x(vec.x()), y(vec.y()), z(vec.z()) {}
operator zeus::CVector3f() const { return {x, y, z}; }
bool operator==(const Vec3&) const = default; bool operator==(const Vec3&) const = default;
}; };

View File

@ -221,6 +221,30 @@ static bool poll_events() noexcept {
return true; return true;
} }
static SDL_Window* create_window(wgpu::BackendType type) {
Uint32 flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE;
switch (type) {
#ifdef DAWN_ENABLE_BACKEND_VULKAN
case wgpu::BackendType::Vulkan:
flags |= SDL_WINDOW_VULKAN;
break;
#endif
#ifdef DAWN_ENABLE_BACKEND_METAL
case wgpu::BackendType::Metal:
flags |= SDL_WINDOW_METAL;
break;
#endif
#ifdef DAWN_ENABLE_BACKEND_OPENGL
case wgpu::BackendType::OpenGL:
flags |= SDL_WINDOW_OPENGL;
break;
#endif
default:
break;
}
return SDL_CreateWindow("Metaforce", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1280, 960, flags);
}
void app_run(std::unique_ptr<AppDelegate> app, Icon icon, int argc, char** argv) noexcept { void app_run(std::unique_ptr<AppDelegate> app, Icon icon, int argc, char** argv) noexcept {
g_AppDelegate = std::move(app); g_AppDelegate = std::move(app);
/* Lets gather arguments skipping the program filename */ /* Lets gather arguments skipping the program filename */
@ -244,34 +268,25 @@ void app_run(std::unique_ptr<AppDelegate> app, Icon icon, int argc, char** argv)
/* TODO: Make this an option rather than hard coding it */ /* TODO: Make this an option rather than hard coding it */
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE; for (const auto backendType : gpu::PreferredBackendOrder) {
switch (gpu::preferredBackendType) { auto* window = create_window(backendType);
#ifdef DAWN_ENABLE_BACKEND_VULKAN if (window == nullptr) {
case wgpu::BackendType::Vulkan: continue;
flags |= SDL_WINDOW_VULKAN; }
break; g_window = window;
#endif if (gpu::initialize(window, backendType)) {
#ifdef DAWN_ENABLE_BACKEND_METAL break;
case wgpu::BackendType::Metal: }
flags |= SDL_WINDOW_METAL; g_window = nullptr;
break; SDL_DestroyWindow(window);
#endif
#ifdef DAWN_ENABLE_BACKEND_OPENGL
case wgpu::BackendType::OpenGL:
flags |= SDL_WINDOW_OPENGL;
break;
#endif
default:
break;
} }
g_window = SDL_CreateWindow("Metaforce", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1280, 960, flags);
if (g_window == nullptr) { if (g_window == nullptr) {
Log.report(logvisor::Fatal, FMT_STRING("Error creating window: {}"), SDL_GetError()); Log.report(logvisor::Fatal, FMT_STRING("Error creating window: {}"), SDL_GetError());
unreachable(); unreachable();
} }
set_window_icon(std::move(icon)); set_window_icon(std::move(icon));
SDL_ShowWindow(g_window);
gpu::initialize(g_window);
gfx::initialize(); gfx::initialize();
imgui::create_context(); imgui::create_context();

View File

@ -1,5 +1,14 @@
#include "BackendBinding.hpp" #include "BackendBinding.hpp"
#if defined(DAWN_ENABLE_BACKEND_D3D12)
#include <dawn/native/D3D12Backend.h>
#endif
#if defined(DAWN_ENABLE_BACKEND_METAL)
#include <dawn/native/MetalBackend.h>
#endif
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
#include <dawn/native/VulkanBackend.h>
#endif
#if defined(DAWN_ENABLE_BACKEND_OPENGL) #if defined(DAWN_ENABLE_BACKEND_OPENGL)
#include <SDL_video.h> #include <SDL_video.h>
#include <dawn/native/OpenGLBackend.h> #include <dawn/native/OpenGLBackend.h>
@ -25,23 +34,44 @@ BackendBinding* CreateVulkanBinding(SDL_Window* window, WGPUDevice device);
BackendBinding::BackendBinding(SDL_Window* window, WGPUDevice device) : m_window(window), m_device(device) {} BackendBinding::BackendBinding(SDL_Window* window, WGPUDevice device) : m_window(window), m_device(device) {}
void DiscoverAdapter(dawn::native::Instance* instance, SDL_Window* window, wgpu::BackendType type) { bool DiscoverAdapter(dawn::native::Instance* instance, SDL_Window* window, wgpu::BackendType type) {
if (type == wgpu::BackendType::OpenGL || type == wgpu::BackendType::OpenGLES) { switch (type) {
#if defined(DAWN_ENABLE_BACKEND_D3D12)
case wgpu::BackendType::D3D12: {
dawn::native::d3d12::AdapterDiscoveryOptions options;
return instance->DiscoverAdapters(&options);
}
#endif
#if defined(DAWN_ENABLE_BACKEND_METAL)
case wgpu::BackendType::Metal: {
dawn::native::metal::AdapterDiscoveryOptions options;
return instance->DiscoverAdapters(&options);
}
#endif
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
case wgpu::BackendType::Vulkan: {
dawn::native::vulkan::AdapterDiscoveryOptions options;
return instance->DiscoverAdapters(&options);
}
#endif
#if defined(DAWN_ENABLE_BACKEND_OPENGL) #if defined(DAWN_ENABLE_BACKEND_OPENGL)
case wgpu::BackendType::OpenGL:
case wgpu::BackendType::OpenGLES: {
SDL_GL_CreateContext(window); SDL_GL_CreateContext(window);
auto getProc = reinterpret_cast<void* (*)(const char*)>(SDL_GL_GetProcAddress); auto getProc = reinterpret_cast<void* (*)(const char*)>(SDL_GL_GetProcAddress);
if (type == wgpu::BackendType::OpenGL) { if (type == wgpu::BackendType::OpenGL) {
dawn::native::opengl::AdapterDiscoveryOptions adapterOptions; dawn::native::opengl::AdapterDiscoveryOptions adapterOptions;
adapterOptions.getProc = getProc; adapterOptions.getProc = getProc;
instance->DiscoverAdapters(&adapterOptions); return instance->DiscoverAdapters(&adapterOptions);
} else { } else {
dawn::native::opengl::AdapterDiscoveryOptionsES adapterOptions; dawn::native::opengl::AdapterDiscoveryOptionsES adapterOptions;
adapterOptions.getProc = getProc; adapterOptions.getProc = getProc;
instance->DiscoverAdapters(&adapterOptions); return instance->DiscoverAdapters(&adapterOptions);
} }
}
#endif #endif
} else { default:
instance->DiscoverDefaultAdapters(); return false;
} }
} }

View File

@ -21,7 +21,7 @@ protected:
WGPUDevice m_device = nullptr; WGPUDevice m_device = nullptr;
}; };
void DiscoverAdapter(dawn::native::Instance* instance, SDL_Window* window, wgpu::BackendType type); bool DiscoverAdapter(dawn::native::Instance* instance, SDL_Window* window, wgpu::BackendType type);
BackendBinding* CreateBinding(wgpu::BackendType type, SDL_Window* window, WGPUDevice device); BackendBinding* CreateBinding(wgpu::BackendType type, SDL_Window* window, WGPUDevice device);
} // namespace aurora::gpu::utils } // namespace aurora::gpu::utils

View File

@ -4,7 +4,11 @@
#include <cassert> #include <cassert>
#include <dawn/native/VulkanBackend.h> #include <dawn/native/VulkanBackend.h>
#include <logvisor/logvisor.hpp>
namespace aurora::gpu::utils { namespace aurora::gpu::utils {
static logvisor::Module Log("aurora::gpu::utils::VulkanBinding");
class VulkanBinding : public BackendBinding { class VulkanBinding : public BackendBinding {
public: public:
VulkanBinding(SDL_Window* window, WGPUDevice device) : BackendBinding(window, device) {} VulkanBinding(SDL_Window* window, WGPUDevice device) : BackendBinding(window, device) {}
@ -29,7 +33,7 @@ private:
void CreateSwapChainImpl() { void CreateSwapChainImpl() {
VkSurfaceKHR surface = VK_NULL_HANDLE; VkSurfaceKHR surface = VK_NULL_HANDLE;
if (SDL_Vulkan_CreateSurface(m_window, dawn::native::vulkan::GetInstance(m_device), &surface) != SDL_TRUE) { if (SDL_Vulkan_CreateSurface(m_window, dawn::native::vulkan::GetInstance(m_device), &surface) != SDL_TRUE) {
assert(false); Log.report(logvisor::Fatal, FMT_STRING("Failed to create Vulkan surface: {}"), SDL_GetError());
} }
m_swapChainImpl = dawn::native::vulkan::CreateNativeSwapChainImpl(m_device, surface); m_swapChainImpl = dawn::native::vulkan::CreateNativeSwapChainImpl(m_device, surface);
} }

View File

@ -26,8 +26,10 @@ constexpr uint64_t UniformBufferSize = 3145728; // 3mb
constexpr uint64_t VertexBufferSize = 3145728; // 3mb constexpr uint64_t VertexBufferSize = 3145728; // 3mb
constexpr uint64_t IndexBufferSize = 1048576; // 1mb constexpr uint64_t IndexBufferSize = 1048576; // 1mb
constexpr uint64_t StorageBufferSize = 8388608; // 8mb constexpr uint64_t StorageBufferSize = 8388608; // 8mb
constexpr uint64_t TextureUploadSize = 8388608; // 8mb
constexpr uint64_t StagingBufferSize = UniformBufferSize + VertexBufferSize + IndexBufferSize + StorageBufferSize; constexpr uint64_t StagingBufferSize =
UniformBufferSize + VertexBufferSize + IndexBufferSize + StorageBufferSize + TextureUploadSize;
struct ShaderState { struct ShaderState {
movie_player::State moviePlayer; movie_player::State moviePlayer;
@ -112,6 +114,7 @@ static ByteBuffer g_uniforms;
static ByteBuffer g_indices; static ByteBuffer g_indices;
static ByteBuffer g_storage; static ByteBuffer g_storage;
static ByteBuffer g_staticStorage; static ByteBuffer g_staticStorage;
static ByteBuffer g_textureUpload;
wgpu::Buffer g_vertexBuffer; wgpu::Buffer g_vertexBuffer;
wgpu::Buffer g_uniformBuffer; wgpu::Buffer g_uniformBuffer;
wgpu::Buffer g_indexBuffer; wgpu::Buffer g_indexBuffer;
@ -134,6 +137,7 @@ struct RenderPass {
static std::vector<RenderPass> g_renderPasses; static std::vector<RenderPass> g_renderPasses;
static u32 g_currentRenderPass; static u32 g_currentRenderPass;
std::vector<TextureHandle> g_resolvedTextures; std::vector<TextureHandle> g_resolvedTextures;
std::vector<TextureUpload> g_textureUploads;
static ByteBuffer g_serializedPipelines{}; static ByteBuffer g_serializedPipelines{};
static u32 g_serializedPipelineCount = 0; static u32 g_serializedPipelineCount = 0;
@ -420,6 +424,7 @@ void shutdown() {
gx::shutdown(); gx::shutdown();
g_resolvedTextures.clear();
g_cachedBindGroups.clear(); g_cachedBindGroups.clear();
g_cachedSamplers.clear(); g_cachedSamplers.clear();
g_pipelines.clear(); g_pipelines.clear();
@ -464,6 +469,7 @@ void begin_frame() {
mapBuffer(g_uniforms, UniformBufferSize); mapBuffer(g_uniforms, UniformBufferSize);
mapBuffer(g_indices, IndexBufferSize); mapBuffer(g_indices, IndexBufferSize);
mapBuffer(g_storage, StorageBufferSize); mapBuffer(g_storage, StorageBufferSize);
mapBuffer(g_textureUpload, TextureUploadSize);
g_renderPasses.emplace_back(); g_renderPasses.emplace_back();
g_currentRenderPass = 0; g_currentRenderPass = 0;
@ -491,6 +497,23 @@ void end_frame(const wgpu::CommandEncoder& cmd) {
g_lastUniformSize = writeBuffer(g_uniforms, g_uniformBuffer, UniformBufferSize, "Uniform"); g_lastUniformSize = writeBuffer(g_uniforms, g_uniformBuffer, UniformBufferSize, "Uniform");
g_lastIndexSize = writeBuffer(g_indices, g_indexBuffer, IndexBufferSize, "Index"); g_lastIndexSize = writeBuffer(g_indices, g_indexBuffer, IndexBufferSize, "Index");
g_lastStorageSize = writeBuffer(g_storage, g_storageBuffer, StorageBufferSize, "Storage"); g_lastStorageSize = writeBuffer(g_storage, g_storageBuffer, StorageBufferSize, "Storage");
{
// Perform texture copies
for (const auto& item : g_textureUploads) {
const wgpu::ImageCopyBuffer buf{
.layout =
wgpu::TextureDataLayout{
.offset = item.layout.offset + bufferOffset,
.bytesPerRow = ALIGN(item.layout.bytesPerRow, 256),
.rowsPerImage = item.layout.rowsPerImage,
},
.buffer = g_stagingBuffers[currentStagingBuffer],
};
cmd.CopyBufferToTexture(&buf, &item.tex, &item.size);
}
g_textureUploads.clear();
g_textureUpload.clear();
}
currentStagingBuffer = (currentStagingBuffer + 1) % g_stagingBuffers.size(); currentStagingBuffer = (currentStagingBuffer + 1) % g_stagingBuffers.size();
map_staging_buffer(); map_staging_buffer();
} }
@ -676,6 +699,18 @@ Range push_static_storage(const uint8_t* data, size_t length) {
range.isStatic = true; range.isStatic = true;
return range; return range;
} }
Range push_texture_data(const uint8_t* data, size_t length, u32 bytesPerRow, u32 rowsPerImage) {
// For CopyBufferToTexture, we need an alignment of 256 per row (see Dawn kTextureBytesPerRowAlignment)
const auto copyBytesPerRow = ALIGN(bytesPerRow, 256);
const auto range = map(g_textureUpload, copyBytesPerRow * rowsPerImage, 0);
u8* dst = g_textureUpload.data() + range.offset;
for (u32 i = 0; i < rowsPerImage; ++i) {
memcpy(dst, data, bytesPerRow);
data += bytesPerRow;
dst += copyBytesPerRow;
}
return range;
}
std::pair<ByteBuffer, Range> map_verts(size_t length) { std::pair<ByteBuffer, Range> map_verts(size_t length) {
const auto range = map(g_verts, length, 4); const auto range = map(g_verts, length, 4);
return {ByteBuffer{g_verts.data() + range.offset, range.size}, range}; return {ByteBuffer{g_verts.data() + range.offset, range.size}, range};

View File

@ -125,6 +125,15 @@ extern wgpu::Buffer g_uniformBuffer;
extern wgpu::Buffer g_indexBuffer; extern wgpu::Buffer g_indexBuffer;
extern wgpu::Buffer g_storageBuffer; extern wgpu::Buffer g_storageBuffer;
extern size_t g_staticStorageLastSize; extern size_t g_staticStorageLastSize;
struct TextureUpload {
wgpu::TextureDataLayout layout;
wgpu::ImageCopyTexture tex;
wgpu::Extent3D size;
TextureUpload(wgpu::TextureDataLayout layout, wgpu::ImageCopyTexture tex, wgpu::Extent3D size) noexcept
: layout(std::move(layout)), tex(std::move(tex)), size(std::move(size)) {}
};
extern std::vector<TextureUpload> g_textureUploads;
// TODO this is a bad place for this... // TODO this is a bad place for this...
extern std::vector<TextureHandle> g_resolvedTextures; extern std::vector<TextureHandle> g_resolvedTextures;
@ -210,6 +219,7 @@ template <typename T>
static inline Range push_static_storage(const T& data) { static inline Range push_static_storage(const T& data) {
return push_static_storage(reinterpret_cast<const uint8_t*>(&data), sizeof(T)); return push_static_storage(reinterpret_cast<const uint8_t*>(&data), sizeof(T));
} }
Range push_texture_data(const uint8_t* data, size_t length, u32 bytesPerRow, u32 rowsPerImage);
std::pair<ByteBuffer, Range> map_verts(size_t length); std::pair<ByteBuffer, Range> map_verts(size_t length);
std::pair<ByteBuffer, Range> map_indices(size_t length); std::pair<ByteBuffer, Range> map_indices(size_t length);
std::pair<ByteBuffer, Range> map_uniform(size_t length); std::pair<ByteBuffer, Range> map_uniform(size_t length);

View File

@ -515,7 +515,7 @@ void GXInitTexObj(GXTexObj* obj, const void* data, u16 width, u16 height, GX::Te
obj->dataInvalidated = true; obj->dataInvalidated = true;
} }
void GXInitTexObjResolved(GXTexObj* obj, u32 bindIdx, GX::TextureFormat format, GXTexWrapMode wrapS, void GXInitTexObjResolved(GXTexObj* obj, u32 bindIdx, GX::TextureFormat format, GXTexWrapMode wrapS,
GXTexWrapMode wrapT) { GXTexWrapMode wrapT, GXTlut tlut) {
const auto& ref = aurora::gfx::g_resolvedTextures[bindIdx]; const auto& ref = aurora::gfx::g_resolvedTextures[bindIdx];
obj->ref = ref; obj->ref = ref;
obj->data = nullptr; obj->data = nullptr;
@ -525,7 +525,8 @@ void GXInitTexObjResolved(GXTexObj* obj, u32 bindIdx, GX::TextureFormat format,
obj->fmt = format; obj->fmt = format;
obj->wrapS = wrapS; obj->wrapS = wrapS;
obj->wrapT = wrapT; obj->wrapT = wrapT;
obj->hasMips = false; // TODO obj->hasMips = false;
obj->tlut = tlut;
// TODO default values? // TODO default values?
obj->minFilter = GX_LINEAR; obj->minFilter = GX_LINEAR;
obj->magFilter = GX_LINEAR; obj->magFilter = GX_LINEAR;
@ -535,7 +536,6 @@ void GXInitTexObjResolved(GXTexObj* obj, u32 bindIdx, GX::TextureFormat format,
obj->biasClamp = false; obj->biasClamp = false;
obj->doEdgeLod = false; obj->doEdgeLod = false;
obj->maxAniso = GX_ANISO_4; obj->maxAniso = GX_ANISO_4;
obj->tlut = GX_TLUT0;
obj->dataInvalidated = false; obj->dataInvalidated = false;
} }
void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter minFilt, GXTexFilter magFilt, float minLod, float maxLod, float lodBias, void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter minFilt, GXTexFilter magFilt, float minLod, float maxLod, float lodBias,
@ -545,6 +545,7 @@ void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter minFilt, GXTexFilter magFilt, fl
obj->minLod = minLod; obj->minLod = minLod;
obj->maxLod = maxLod; obj->maxLod = maxLod;
obj->lodBias = lodBias; obj->lodBias = lodBias;
obj->biasClamp = biasClamp;
obj->doEdgeLod = doEdgeLod; obj->doEdgeLod = doEdgeLod;
obj->maxAniso = maxAniso; obj->maxAniso = maxAniso;
} }
@ -611,6 +612,18 @@ void GXInitTlutObj(GXTlutObj* obj, const void* data, GXTlutFmt format, u16 entri
"GXInitTlutObj"); "GXInitTlutObj");
} }
void GXLoadTlut(const GXTlutObj* obj, GXTlut idx) noexcept { g_gxState.tluts[idx] = *obj; } void GXLoadTlut(const GXTlutObj* obj, GXTlut idx) noexcept { g_gxState.tluts[idx] = *obj; }
void GXSetColorUpdate(GXBool enabled) noexcept { g_gxState.colorUpdate = enabled; }
void GXSetTevColorS10(GX::TevRegID id, const GXColorS10& color) noexcept {
g_gxState.colorRegs[id] = zeus::CColor{
static_cast<float>(color.r) / 1023.f,
static_cast<float>(color.g) / 1023.f,
static_cast<float>(color.b) / 1023.f,
static_cast<float>(color.a) / 1023.f,
};
}
void GXInvalidateTexAll() noexcept {
// no-op?
}
namespace aurora::gfx { namespace aurora::gfx {
static logvisor::Module Log("aurora::gfx::gx"); static logvisor::Module Log("aurora::gfx::gx");
@ -771,10 +784,13 @@ static inline wgpu::BlendState to_blend_state(GX::BlendMode mode, GX::BlendFacto
}; };
} }
static inline wgpu::ColorWriteMask to_write_mask(bool alphaUpdate) { static inline wgpu::ColorWriteMask to_write_mask(bool colorUpdate, bool alphaUpdate) {
auto writeMask = wgpu::ColorWriteMask::Red | wgpu::ColorWriteMask::Green | wgpu::ColorWriteMask::Blue; auto writeMask = wgpu::ColorWriteMask::None;
if (colorUpdate) {
writeMask |= wgpu::ColorWriteMask::Red | wgpu::ColorWriteMask::Green | wgpu::ColorWriteMask::Blue;
}
if (alphaUpdate) { if (alphaUpdate) {
writeMask = writeMask | wgpu::ColorWriteMask::Alpha; writeMask |= wgpu::ColorWriteMask::Alpha;
} }
return writeMask; return writeMask;
} }
@ -791,25 +807,23 @@ static inline wgpu::PrimitiveState to_primitive_state(GX::Primitive gx_prim, GX:
Log.report(logvisor::Fatal, FMT_STRING("Unsupported primitive type {}"), gx_prim); Log.report(logvisor::Fatal, FMT_STRING("Unsupported primitive type {}"), gx_prim);
unreachable(); unreachable();
} }
wgpu::FrontFace frontFace = wgpu::FrontFace::CCW;
wgpu::CullMode cullMode = wgpu::CullMode::None; wgpu::CullMode cullMode = wgpu::CullMode::None;
switch (gx_cullMode) { switch (gx_cullMode) {
case GX::CULL_FRONT: case GX::CULL_FRONT:
frontFace = wgpu::FrontFace::CW;
cullMode = wgpu::CullMode::Front; cullMode = wgpu::CullMode::Front;
break; break;
case GX::CULL_BACK: case GX::CULL_BACK:
cullMode = wgpu::CullMode::Back; cullMode = wgpu::CullMode::Back;
break; break;
case GX::CULL_ALL: case GX::CULL_NONE:
break;
default:
Log.report(logvisor::Fatal, FMT_STRING("Unsupported cull mode {}"), gx_cullMode); Log.report(logvisor::Fatal, FMT_STRING("Unsupported cull mode {}"), gx_cullMode);
unreachable(); unreachable();
default:
break;
} }
return { return {
.topology = primitive, .topology = primitive,
.frontFace = frontFace, .frontFace = wgpu::FrontFace::CW,
.cullMode = cullMode, .cullMode = cullMode,
}; };
} }
@ -827,7 +841,7 @@ wgpu::RenderPipeline build_pipeline(const PipelineConfig& config, const ShaderIn
const std::array colorTargets{wgpu::ColorTargetState{ const std::array colorTargets{wgpu::ColorTargetState{
.format = g_graphicsConfig.colorFormat, .format = g_graphicsConfig.colorFormat,
.blend = &blendState, .blend = &blendState,
.writeMask = to_write_mask(config.alphaUpdate), .writeMask = to_write_mask(config.colorUpdate, config.alphaUpdate),
}}; }};
const auto fragmentState = wgpu::FragmentState{ const auto fragmentState = wgpu::FragmentState{
.module = shader, .module = shader,
@ -888,22 +902,13 @@ void populate_pipeline_config(PipelineConfig& config, GX::Primitive primitive) n
[](const auto type) { return type == GX::INDEX8 || type == GX::INDEX16; }); [](const auto type) { return type == GX::INDEX8 || type == GX::INDEX16; });
for (u8 i = 0; i < MaxTextures; ++i) { for (u8 i = 0; i < MaxTextures; ++i) {
const auto& bind = g_gxState.textures[i]; const auto& bind = g_gxState.textures[i];
GX::TextureFormat copyFmt, bindFmt; TextureConfig texConfig{};
bool flipUV = false; if (bind.texObj.ref) {
if (!bind.texObj.ref) { texConfig.copyFmt = bind.texObj.ref->gxFormat;
config.shaderConfig.textureConfig[i] = {}; texConfig.loadFmt = bind.texObj.fmt;
continue; texConfig.renderTex = bind.texObj.ref->isRenderTexture;
} else if (bind.texObj.ref->isRenderTexture) {
// EFB copy
copyFmt = bind.texObj.ref->gxFormat;
bindFmt = bind.texObj.fmt;
flipUV = true;
} else {
// Loaded texture object, no conversion necessary
copyFmt = InvalidTextureFormat;
bindFmt = bind.texObj.fmt;
} }
config.shaderConfig.textureConfig[i] = {copyFmt, bindFmt, flipUV}; config.shaderConfig.textureConfig[i] = texConfig;
} }
config = { config = {
.shaderConfig = config.shaderConfig, .shaderConfig = config.shaderConfig,
@ -918,6 +923,7 @@ void populate_pipeline_config(PipelineConfig& config, GX::Primitive primitive) n
.depthCompare = g_gxState.depthCompare, .depthCompare = g_gxState.depthCompare,
.depthUpdate = g_gxState.depthUpdate, .depthUpdate = g_gxState.depthUpdate,
.alphaUpdate = g_gxState.alphaUpdate, .alphaUpdate = g_gxState.alphaUpdate,
.colorUpdate = g_gxState.colorUpdate,
}; };
} }
@ -983,7 +989,7 @@ Range build_uniform(const ShaderInfo& info) noexcept {
const auto& mat = std::get<Mat4x4<float>>(g_gxState.texMtxs[i]); const auto& mat = std::get<Mat4x4<float>>(g_gxState.texMtxs[i]);
buf.append(&mat, 64); buf.append(&mat, 64);
} else { } else {
// Log.report(logvisor::Fatal, FMT_STRING("expected 3x4 mtx in idx {}"), i); Log.report(logvisor::Fatal, FMT_STRING("expected 3x4 mtx in idx {}"), i);
buf.append(&Mat4x4_Identity, 64); buf.append(&Mat4x4_Identity, 64);
} }
break; break;
@ -1073,28 +1079,28 @@ GXBindGroups build_bind_groups(const ShaderInfo& info, const ShaderConfig& confi
std::array<wgpu::BindGroupEntry, MaxTextures * 2> textureEntries; std::array<wgpu::BindGroupEntry, MaxTextures * 2> textureEntries;
u32 samplerCount = 0; u32 samplerCount = 0;
u32 textureCount = 0; u32 textureCount = 0;
for (u32 texIdx = 0, i = 0; texIdx < info.sampledTextures.size(); ++texIdx) { for (u32 i = 0; i < info.sampledTextures.size(); ++i) {
if (!info.sampledTextures.test(texIdx)) { if (!info.sampledTextures.test(i)) {
continue; continue;
} }
const auto& tex = g_gxState.textures[texIdx]; const auto& tex = g_gxState.textures[i];
if (!tex) { if (!tex) {
Log.report(logvisor::Fatal, FMT_STRING("unbound texture {}"), texIdx); Log.report(logvisor::Fatal, FMT_STRING("unbound texture {}"), i);
unreachable(); unreachable();
} }
samplerEntries[i] = { samplerEntries[samplerCount] = {
.binding = i, .binding = samplerCount,
.sampler = sampler_ref(tex.get_descriptor()), .sampler = sampler_ref(tex.get_descriptor()),
}; };
++samplerCount; ++samplerCount;
textureEntries[i] = { textureEntries[textureCount] = {
.binding = i, .binding = textureCount,
.textureView = tex.texObj.ref->view, .textureView = tex.texObj.ref->view,
}; };
++textureCount;
// Load palette // Load palette
const auto& texConfig = config.textureConfig[i]; const auto& texConfig = config.textureConfig[i];
if (texConfig.loadFmt == GX::TF_C4 || texConfig.loadFmt == GX::TF_C8 || texConfig.loadFmt == GX::TF_C14X2) { if (texConfig.loadFmt == GX::TF_C4 || texConfig.loadFmt == GX::TF_C8 || texConfig.loadFmt == GX::TF_C14X2) {
++i;
u32 tlut = tex.texObj.tlut; u32 tlut = tex.texObj.tlut;
if (tlut < GX_TLUT0 || tlut > GX_TLUT7) { if (tlut < GX_TLUT0 || tlut > GX_TLUT7) {
Log.report(logvisor::Fatal, FMT_STRING("tlut out of bounds {}"), tlut); Log.report(logvisor::Fatal, FMT_STRING("tlut out of bounds {}"), tlut);
@ -1103,15 +1109,12 @@ GXBindGroups build_bind_groups(const ShaderInfo& info, const ShaderConfig& confi
Log.report(logvisor::Fatal, FMT_STRING("tlut unbound {}"), tlut); Log.report(logvisor::Fatal, FMT_STRING("tlut unbound {}"), tlut);
unreachable(); unreachable();
} }
textureEntries[i] = { textureEntries[textureCount] = {
.binding = i, .binding = textureCount,
.textureView = g_gxState.tluts[tlut].ref->view, .textureView = g_gxState.tluts[tlut].ref->view,
}; };
textureCount += 2;
} else {
++textureCount; ++textureCount;
} }
i++;
} }
return { return {
.uniformBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{ .uniformBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{
@ -1199,77 +1202,82 @@ GXBindGroupLayouts build_bind_group_layouts(const ShaderInfo& info, const Shader
sUniformBindGroupLayouts.try_emplace(uniformSizeKey, out.uniformLayout); sUniformBindGroupLayouts.try_emplace(uniformSizeKey, out.uniformLayout);
} }
u32 textureCount = info.sampledTextures.count(); // u32 textureCount = info.sampledTextures.count();
// const auto textureIt = sTextureBindGroupLayouts.find(textureCount); // const auto textureIt = sTextureBindGroupLayouts.find(textureCount);
// if (textureIt != sTextureBindGroupLayouts.end()) { // if (textureIt != sTextureBindGroupLayouts.end()) {
// const auto& [sl, tl] = textureIt->second; // const auto& [sl, tl] = textureIt->second;
// out.samplerLayout = sl; // out.samplerLayout = sl;
// out.textureLayout = tl; // out.textureLayout = tl;
// } else { // } else {
u32 numSamplers = 0; u32 numSamplers = 0;
u32 numTextures = 0; u32 numTextures = 0;
std::array<wgpu::BindGroupLayoutEntry, MaxTextures> samplerEntries; std::array<wgpu::BindGroupLayoutEntry, MaxTextures> samplerEntries;
std::array<wgpu::BindGroupLayoutEntry, MaxTextures * 2> textureEntries; std::array<wgpu::BindGroupLayoutEntry, MaxTextures * 2> textureEntries;
for (u32 i = 0, t = 0; i < textureCount; ++i, ++t) { for (u32 i = 0; i < info.sampledTextures.size(); ++i) {
samplerEntries[i] = { if (!info.sampledTextures.test(i)) {
.binding = i, continue;
}
samplerEntries[numSamplers] = {
.binding = numSamplers,
.visibility = wgpu::ShaderStage::Fragment,
.sampler = {.type = wgpu::SamplerBindingType::Filtering},
};
++numSamplers;
const auto& texConfig = config.textureConfig[i];
if (texConfig.loadFmt == GX::TF_C4 || texConfig.loadFmt == GX::TF_C8 || texConfig.loadFmt == GX::TF_C14X2) {
bool isPaletted =
texConfig.copyFmt == GX::TF_C4 || texConfig.copyFmt == GX::TF_C8 || texConfig.loadFmt == GX::TF_C14X2;
textureEntries[numTextures] = {
.binding = numTextures,
.visibility = wgpu::ShaderStage::Fragment, .visibility = wgpu::ShaderStage::Fragment,
.sampler = {.type = wgpu::SamplerBindingType::Filtering}, .texture =
{
.sampleType = isPaletted ? wgpu::TextureSampleType::Sint : wgpu::TextureSampleType::Float,
.viewDimension = wgpu::TextureViewDimension::e2D,
},
}; };
++numSamplers; ++numTextures;
const auto& texConfig = config.textureConfig[i]; textureEntries[numTextures] = {
if (texConfig.loadFmt == GX::TF_C4 || texConfig.loadFmt == GX::TF_C8 || texConfig.loadFmt == GX::TF_C14X2) { .binding = numTextures,
textureEntries[t] = { .visibility = wgpu::ShaderStage::Fragment,
.binding = t, .texture =
.visibility = wgpu::ShaderStage::Fragment, {
.texture = .sampleType = wgpu::TextureSampleType::Float,
{ .viewDimension = wgpu::TextureViewDimension::e2D,
.sampleType = wgpu::TextureSampleType::Sint, },
.viewDimension = wgpu::TextureViewDimension::e2D,
},
};
++t;
textureEntries[t] = {
.binding = t,
.visibility = wgpu::ShaderStage::Fragment,
.texture =
{
.sampleType = wgpu::TextureSampleType::Float,
.viewDimension = wgpu::TextureViewDimension::e2D,
},
};
numTextures += 2;
} else {
textureEntries[t] = {
.binding = t,
.visibility = wgpu::ShaderStage::Fragment,
.texture =
{
.sampleType = wgpu::TextureSampleType::Float,
.viewDimension = wgpu::TextureViewDimension::e2D,
},
};
++numTextures;
}
}
{
const wgpu::BindGroupLayoutDescriptor descriptor{
.label = "GX Sampler Bind Group",
.entryCount = numSamplers,
.entries = samplerEntries.data(),
}; };
out.samplerLayout = g_device.CreateBindGroupLayout(&descriptor); ++numTextures;
} } else {
{ textureEntries[numTextures] = {
const wgpu::BindGroupLayoutDescriptor descriptor{ .binding = numTextures,
.label = "GX Texture Bind Group", .visibility = wgpu::ShaderStage::Fragment,
.entryCount = numTextures, .texture =
.entries = textureEntries.data(), {
.sampleType = wgpu::TextureSampleType::Float,
.viewDimension = wgpu::TextureViewDimension::e2D,
},
}; };
out.textureLayout = g_device.CreateBindGroupLayout(&descriptor); ++numTextures;
} }
// sTextureBindGroupLayouts.try_emplace(textureCount, out.samplerLayout, out.textureLayout); }
// } {
const wgpu::BindGroupLayoutDescriptor descriptor{
.label = "GX Sampler Bind Group Layout",
.entryCount = numSamplers,
.entries = samplerEntries.data(),
};
out.samplerLayout = g_device.CreateBindGroupLayout(&descriptor);
}
{
const wgpu::BindGroupLayoutDescriptor descriptor{
.label = "GX Texture Bind Group Layout",
.entryCount = numTextures,
.entries = textureEntries.data(),
};
out.textureLayout = g_device.CreateBindGroupLayout(&descriptor);
}
// sTextureBindGroupLayouts.try_emplace(textureCount, out.samplerLayout, out.textureLayout);
// }
return out; return out;
} }

View File

@ -188,6 +188,7 @@ struct GXState {
std::array<IndTexMtxInfo, MaxIndTexMtxs> indTexMtxs; std::array<IndTexMtxInfo, MaxIndTexMtxs> indTexMtxs;
bool depthCompare = true; bool depthCompare = true;
bool depthUpdate = true; bool depthUpdate = true;
bool colorUpdate = true;
bool alphaUpdate = true; bool alphaUpdate = true;
u8 numChans = 0; u8 numChans = 0;
u8 numIndStages = 0; u8 numIndStages = 0;
@ -202,9 +203,9 @@ void shutdown() noexcept;
const TextureBind& get_texture(GX::TexMapID id) noexcept; const TextureBind& get_texture(GX::TexMapID id) noexcept;
struct TextureConfig { struct TextureConfig {
GX::TextureFormat copyFmt = InvalidTextureFormat; // GXSetTexCopyDst GX::TextureFormat copyFmt = InvalidTextureFormat; // Underlying texture format
GX::TextureFormat loadFmt = InvalidTextureFormat; // GXTexObj format GX::TextureFormat loadFmt = InvalidTextureFormat; // Texture format being bound
bool flipUV = false; // For render textures bool renderTex = false; // Perform conversion / flip UVs
u8 _p1 = 0; u8 _p1 = 0;
u8 _p2 = 0; u8 _p2 = 0;
u8 _p3 = 0; u8 _p3 = 0;
@ -225,7 +226,7 @@ struct ShaderConfig {
}; };
static_assert(std::has_unique_object_representations_v<ShaderConfig>); static_assert(std::has_unique_object_representations_v<ShaderConfig>);
constexpr u32 GXPipelineConfigVersion = 3; constexpr u32 GXPipelineConfigVersion = 4;
struct PipelineConfig { struct PipelineConfig {
u32 version = GXPipelineConfigVersion; u32 version = GXPipelineConfigVersion;
ShaderConfig shaderConfig; ShaderConfig shaderConfig;
@ -236,8 +237,7 @@ struct PipelineConfig {
GX::BlendFactor blendFacSrc, blendFacDst; GX::BlendFactor blendFacSrc, blendFacDst;
GX::LogicOp blendOp; GX::LogicOp blendOp;
u32 dstAlpha; u32 dstAlpha;
bool depthCompare, depthUpdate, alphaUpdate; bool depthCompare, depthUpdate, alphaUpdate, colorUpdate;
u8 _pad = 0;
}; };
static_assert(std::has_unique_object_representations_v<PipelineConfig>); static_assert(std::has_unique_object_representations_v<PipelineConfig>);

View File

@ -564,6 +564,7 @@ static inline std::string vtx_attr(const ShaderConfig& config, GX::Attr attr) {
static inline std::string texture_conversion(const TextureConfig& tex, u32 stageIdx, u32 texMapId) { static inline std::string texture_conversion(const TextureConfig& tex, u32 stageIdx, u32 texMapId) {
std::string out; std::string out;
if (tex.renderTex)
switch (tex.copyFmt) { switch (tex.copyFmt) {
default: default:
break; break;
@ -573,13 +574,12 @@ static inline std::string texture_conversion(const TextureConfig& tex, u32 stage
break; break;
case GX::TF_I4: case GX::TF_I4:
case GX::TF_I8: case GX::TF_I8:
// Perform intensity conversion // FIXME HACK
out += fmt::format( if (tex.loadFmt != GX::TF_C4 && tex.loadFmt != GX::TF_C8 && tex.loadFmt != GX::TF_C14X2) {
FMT_STRING("\n {{" // Perform intensity conversion
"\n var intensity = dot(sampled{0}.rgb, vec3(0.257, 0.504, 0.098)) + 16.0 / 255.0;" out += fmt::format(FMT_STRING("\n sampled{0} = vec4<f32>(intensityF32(sampled{0}.rgb), 0.f, 0.f, 1.f);"),
"\n sampled{0} = vec4<f32>(intensity, 0.f, 0.f, 1.f);" stageIdx);
"\n }}"), }
stageIdx);
break; break;
} }
switch (tex.loadFmt) { switch (tex.loadFmt) {
@ -883,7 +883,7 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
if (stage.colorOp.clamp) { if (stage.colorOp.clamp) {
op = fmt::format(FMT_STRING("clamp({}, vec3<f32>(0.0), vec3<f32>(1.0))"), op); op = fmt::format(FMT_STRING("clamp({}, vec3<f32>(0.0), vec3<f32>(1.0))"), op);
} }
fragmentFn += fmt::format(FMT_STRING("\n {0} = vec4<f32>({1}, {0}.a);"), outReg, op); fragmentFn += fmt::format(FMT_STRING("\n // TEV stage {2}\n {0} = vec4<f32>({1}, {0}.a);"), outReg, op, idx);
} }
{ {
std::string outReg; std::string outReg;
@ -1033,7 +1033,6 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
Log.report(logvisor::Fatal, FMT_STRING("unhandled tcg src {} for "), tcg.src); Log.report(logvisor::Fatal, FMT_STRING("unhandled tcg src {} for "), tcg.src);
unreachable(); unreachable();
} }
// TODO this all assumes MTX3x4 currently
if (tcg.mtx == GX::IDENTITY) { if (tcg.mtx == GX::IDENTITY) {
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0}_tmp = tc{0}.xyz;"), i); vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{0}_tmp = tc{0}.xyz;"), i);
} else { } else {
@ -1069,9 +1068,11 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
uvIn = fmt::format(FMT_STRING("in.tex{0}_uv"), stage.texCoordId); uvIn = fmt::format(FMT_STRING("in.tex{0}_uv"), stage.texCoordId);
// } // }
if (texConfig.loadFmt == GX::TF_C4 || texConfig.loadFmt == GX::TF_C8 || texConfig.loadFmt == GX::TF_C14X2) { if (texConfig.loadFmt == GX::TF_C4 || texConfig.loadFmt == GX::TF_C8 || texConfig.loadFmt == GX::TF_C14X2) {
bool isPaletted =
texConfig.copyFmt == GX::TF_C4 || texConfig.copyFmt == GX::TF_C8 || texConfig.loadFmt == GX::TF_C14X2;
fragmentFnPre += fragmentFnPre +=
fmt::format(FMT_STRING("\n var sampled{0} = textureSamplePalette(tex{1}, tex{1}_samp, {2}, tlut{1});"), fmt::format(FMT_STRING("\n var sampled{0} = textureSamplePalette{3}(tex{1}, tex{1}_samp, {2}, tlut{1});"),
i, stage.texMapId, uvIn); i, stage.texMapId, uvIn, isPaletted ? ""sv : "RGB"sv);
} else { } else {
fragmentFnPre += fmt::format( fragmentFnPre += fmt::format(
FMT_STRING("\n var sampled{0} = textureSampleBias(tex{1}, tex{1}_samp, {2}, ubuf.tex{1}_lod);"), i, FMT_STRING("\n var sampled{0} = textureSampleBias(tex{1}, tex{1}_samp, {2}, ubuf.tex{1}_lod);"), i,
@ -1111,7 +1112,7 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
"}"; "}";
uniBufAttrs += "\n fog: Fog,"; uniBufAttrs += "\n fog: Fog,";
fragmentFn += "\n var fogF = clamp((ubuf.fog.a / (ubuf.fog.b - in.pos.z)) - ubuf.fog.c, 0.0, 1.0);"; fragmentFn += "\n // Fog\n var fogF = clamp((ubuf.fog.a / (ubuf.fog.b - in.pos.z)) - ubuf.fog.c, 0.0, 1.0);";
switch (config.fogType) { switch (config.fogType) {
case GX::FOG_PERSP_LIN: case GX::FOG_PERSP_LIN:
case GX::FOG_ORTHO_LIN: case GX::FOG_ORTHO_LIN:
@ -1154,9 +1155,11 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
const auto& texConfig = config.textureConfig[i]; const auto& texConfig = config.textureConfig[i];
if (texConfig.loadFmt == GX::TF_C4 || texConfig.loadFmt == GX::TF_C8 || texConfig.loadFmt == GX::TF_C14X2) { if (texConfig.loadFmt == GX::TF_C4 || texConfig.loadFmt == GX::TF_C8 || texConfig.loadFmt == GX::TF_C14X2) {
bool isPaletted =
texConfig.copyFmt == GX::TF_C4 || texConfig.copyFmt == GX::TF_C8 || texConfig.loadFmt == GX::TF_C14X2;
texBindings += fmt::format(FMT_STRING("\n@group(2) @binding({})\n" texBindings += fmt::format(FMT_STRING("\n@group(2) @binding({})\n"
"var tex{}: texture_2d<i32>;"), "var tex{}: texture_2d<{}>;"),
texBindIdx, i); texBindIdx, i, isPaletted ? "i32"sv : "f32"sv);
++texBindIdx; ++texBindIdx;
texBindings += fmt::format(FMT_STRING("\n@group(2) @binding({})\n" texBindings += fmt::format(FMT_STRING("\n@group(2) @binding({})\n"
"var tlut{}: texture_2d<f32>;"), "var tlut{}: texture_2d<f32>;"),
@ -1175,6 +1178,7 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
std::string comp0 = alpha_compare(config.alphaCompare.comp0, config.alphaCompare.ref0, comp0Valid); std::string comp0 = alpha_compare(config.alphaCompare.comp0, config.alphaCompare.ref0, comp0Valid);
std::string comp1 = alpha_compare(config.alphaCompare.comp1, config.alphaCompare.ref1, comp1Valid); std::string comp1 = alpha_compare(config.alphaCompare.comp1, config.alphaCompare.ref1, comp1Valid);
if (comp0Valid || comp1Valid) { if (comp0Valid || comp1Valid) {
fragmentFn += "\n // Alpha compare";
switch (config.alphaCompare.op) { switch (config.alphaCompare.op) {
case GX::AOP_AND: case GX::AOP_AND:
fragmentFn += fmt::format(FMT_STRING("\n if (!({} && {})) {{ discard; }}"), comp0, comp1); fragmentFn += fmt::format(FMT_STRING("\n if (!({} && {})) {{ discard; }}"), comp0, comp1);
@ -1212,17 +1216,48 @@ struct VertexOutput {{
@builtin(position) pos: vec4<f32>,{vtxOutAttrs} @builtin(position) pos: vec4<f32>,{vtxOutAttrs}
}}; }};
fn intensityF32(rgb: vec3<f32>) -> f32 {{
// RGB to intensity conversion
// https://github.com/dolphin-emu/dolphin/blob/4cd48e609c507e65b95bca5afb416b59eaf7f683/Source/Core/VideoCommon/TextureConverterShaderGen.cpp#L237-L241
return dot(rgb, vec3(0.257, 0.504, 0.098)) + 16.0 / 255.0;
}}
fn intensityI32(rgb: vec3<f32>) -> i32 {{
return i32(dot(rgb, vec3(0.257, 0.504, 0.098)) * 255.f);
}}
fn textureSamplePalette(tex: texture_2d<i32>, samp: sampler, uv: vec2<f32>, tlut: texture_2d<f32>) -> vec4<f32> {{ fn textureSamplePalette(tex: texture_2d<i32>, samp: sampler, uv: vec2<f32>, tlut: texture_2d<f32>) -> vec4<f32> {{
var f = fract(uv * vec2<f32>(textureDimensions(tex)) + 0.5); // Gather index values
var i = textureGather(0, tex, samp, uv); var i = textureGather(0, tex, samp, uv);
var sX = textureLoad(tlut, vec2<i32>(i.x, 0), 0); // Load palette colors
var sY = textureLoad(tlut, vec2<i32>(i.y, 0), 0); var c0 = textureLoad(tlut, vec2<i32>(i[0], 0), 0);
var sZ = textureLoad(tlut, vec2<i32>(i.z, 0), 0); var c1 = textureLoad(tlut, vec2<i32>(i[1], 0), 0);
var sW = textureLoad(tlut, vec2<i32>(i.w, 0), 0); var c2 = textureLoad(tlut, vec2<i32>(i[2], 0), 0);
// Bilinear filtering var c3 = textureLoad(tlut, vec2<i32>(i[3], 0), 0);
var tA = mix(sW, sZ, f.x); // Perform bilinear filtering
var tB = mix(sX, sY, f.x); var f = fract(uv * vec2<f32>(textureDimensions(tex)) + 0.5);
return mix(tA, tB, f.y); var t0 = mix(c3, c2, f.x);
var t1 = mix(c0, c1, f.x);
return mix(t0, t1, f.y);
}}
fn textureSamplePaletteRGB(tex: texture_2d<f32>, samp: sampler, uv: vec2<f32>, tlut: texture_2d<f32>) -> vec4<f32> {{
// Gather RGB channels
var iR = textureGather(0, tex, samp, uv);
var iG = textureGather(1, tex, samp, uv);
var iB = textureGather(2, tex, samp, uv);
// Perform intensity conversion
var i0 = intensityI32(vec3<f32>(iR[0], iG[0], iB[0]));
var i1 = intensityI32(vec3<f32>(iR[1], iG[1], iB[1]));
var i2 = intensityI32(vec3<f32>(iR[2], iG[2], iB[2]));
var i3 = intensityI32(vec3<f32>(iR[3], iG[3], iB[3]));
// Load palette colors
var c0 = textureLoad(tlut, vec2<i32>(i0, 0), 0);
var c1 = textureLoad(tlut, vec2<i32>(i1, 0), 0);
var c2 = textureLoad(tlut, vec2<i32>(i2, 0), 0);
var c3 = textureLoad(tlut, vec2<i32>(i3, 0), 0);
// Perform bilinear filtering
var f = fract(uv * vec2<f32>(textureDimensions(tex)) + 0.5);
var t0 = mix(c3, c2, f.x);
var t1 = mix(c0, c1, f.x);
return mix(t0, t1, f.y);
}} }}
@stage(vertex) @stage(vertex)

View File

@ -71,18 +71,20 @@ TextureHandle new_static_texture_2d(uint32_t width, uint32_t height, uint32_t mi
offset + dataSize, data.size()); offset + dataSize, data.size());
unreachable(); unreachable();
} }
const auto dstView = wgpu::ImageCopyTexture{ auto dstView = wgpu::ImageCopyTexture{
.texture = ref.texture, .texture = ref.texture,
.mipLevel = mip, .mipLevel = mip,
}; };
const auto range = push_texture_data(data.data() + offset, dataSize, bytesPerRow, heightBlocks);
const auto dataLayout = wgpu::TextureDataLayout{ const auto dataLayout = wgpu::TextureDataLayout{
.offset = range.offset,
.bytesPerRow = bytesPerRow, .bytesPerRow = bytesPerRow,
.rowsPerImage = heightBlocks, .rowsPerImage = heightBlocks,
}; };
g_queue.WriteTexture(&dstView, data.data() + offset, dataSize, &dataLayout, &physicalSize); g_textureUploads.emplace_back(dataLayout, std::move(dstView), physicalSize);
offset += dataSize; offset += dataSize;
} }
if (offset < data.size()) { if (data.size() != UINT32_MAX && offset < data.size()) {
Log.report(logvisor::Warning, FMT_STRING("new_static_texture_2d[{}]: texture used {} bytes, but given {} bytes"), Log.report(logvisor::Warning, FMT_STRING("new_static_texture_2d[{}]: texture used {} bytes, but given {} bytes"),
label, offset, data.size()); label, offset, data.size());
} }
@ -112,7 +114,8 @@ TextureHandle new_dynamic_texture_2d(uint32_t width, uint32_t height, uint32_t m
}; };
auto texture = g_device.CreateTexture(&textureDescriptor); auto texture = g_device.CreateTexture(&textureDescriptor);
auto textureView = texture.CreateView(&textureViewDescriptor); auto textureView = texture.CreateView(&textureViewDescriptor);
return std::make_shared<TextureRef>(std::move(texture), std::move(textureView), size, wgpuFormat, mips, format, false); return std::make_shared<TextureRef>(std::move(texture), std::move(textureView), size, wgpuFormat, mips, format,
false);
} }
TextureHandle new_render_texture(uint32_t width, uint32_t height, GX::TextureFormat fmt, zstring_view label) noexcept { TextureHandle new_render_texture(uint32_t width, uint32_t height, GX::TextureFormat fmt, zstring_view label) noexcept {
@ -167,18 +170,20 @@ void write_texture(const TextureRef& ref, ArrayRef<uint8_t> data) noexcept {
data.size()); data.size());
unreachable(); unreachable();
} }
const auto dstView = wgpu::ImageCopyTexture{ auto dstView = wgpu::ImageCopyTexture{
.texture = ref.texture, .texture = ref.texture,
.mipLevel = mip, .mipLevel = mip,
}; };
const auto range = push_texture_data(data.data() + offset, dataSize, bytesPerRow, heightBlocks);
const auto dataLayout = wgpu::TextureDataLayout{ const auto dataLayout = wgpu::TextureDataLayout{
.offset = range.offset,
.bytesPerRow = bytesPerRow, .bytesPerRow = bytesPerRow,
.rowsPerImage = heightBlocks, .rowsPerImage = heightBlocks,
}; };
g_queue.WriteTexture(&dstView, data.data() + offset, dataSize, &dataLayout, &physicalSize); g_textureUploads.emplace_back(dataLayout, std::move(dstView), physicalSize);
offset += dataSize; offset += dataSize;
} }
if (offset < data.size()) { if (data.size() != UINT32_MAX && offset < data.size()) {
Log.report(logvisor::Warning, FMT_STRING("write_texture: texture used {} bytes, but given {} bytes"), offset, Log.report(logvisor::Warning, FMT_STRING("write_texture: texture used {} bytes, but given {} bytes"), offset,
data.size()); data.size());
} }

View File

@ -50,7 +50,8 @@ TextureWithSampler create_render_texture(bool multisampled) {
} }
const auto textureDescriptor = wgpu::TextureDescriptor{ const auto textureDescriptor = wgpu::TextureDescriptor{
.label = "Render texture", .label = "Render texture",
.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst, .usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc |
wgpu::TextureUsage::CopyDst,
.size = size, .size = size,
.format = format, .format = format,
.sampleCount = sampleCount, .sampleCount = sampleCount,
@ -230,27 +231,54 @@ static void error_callback(WGPUErrorType type, char const* message, void* userda
magic_enum::enum_name(static_cast<wgpu::ErrorType>(type)), message); magic_enum::enum_name(static_cast<wgpu::ErrorType>(type)), message);
} }
void initialize(SDL_Window* window) { static void device_callback(WGPURequestDeviceStatus status, WGPUDevice device, char const* message, void* userdata) {
Log.report(logvisor::Info, FMT_STRING("Creating Dawn instance")); if (status == WGPURequestDeviceStatus_Success) {
g_Instance = std::make_unique<dawn::native::Instance>(); g_device = wgpu::Device::Acquire(device);
#if !defined(NDEBUG) } else {
// D3D12's debug layer is very slow Log.report(logvisor::Warning, FMT_STRING("Device request failed with message: {}"), message);
if (preferredBackendType != wgpu::BackendType::D3D12) {
g_Instance->EnableBackendValidation(true);
} }
*static_cast<bool*>(userdata) = true;
}
bool initialize(SDL_Window* window, wgpu::BackendType backendType) {
if (!g_Instance) {
Log.report(logvisor::Info, FMT_STRING("Creating Dawn instance"));
g_Instance = std::make_unique<dawn::native::Instance>();
}
#ifndef NDEBUG
// D3D12's debug layer is very slow
// g_Instance->EnableBackendValidation(backendType != wgpu::BackendType::D3D12);
#endif #endif
utils::DiscoverAdapter(g_Instance.get(), window, preferredBackendType); if (!utils::DiscoverAdapter(g_Instance.get(), window, backendType)) {
return false;
}
{ {
std::vector<dawn::native::Adapter> adapters = g_Instance->GetAdapters(); std::vector<dawn::native::Adapter> adapters = g_Instance->GetAdapters();
const auto adapterIt = std::find_if(adapters.begin(), adapters.end(), [](const auto& adapter) -> bool { std::sort(adapters.begin(), adapters.end(), [&](const auto& a, const auto& b) {
wgpu::AdapterProperties propertiesA;
wgpu::AdapterProperties propertiesB;
a.GetProperties(&propertiesA);
b.GetProperties(&propertiesB);
constexpr std::array PreferredTypeOrder{
wgpu::AdapterType::DiscreteGPU,
wgpu::AdapterType::IntegratedGPU,
wgpu::AdapterType::CPU,
};
const auto typeItA = std::find(PreferredTypeOrder.begin(), PreferredTypeOrder.end(), propertiesA.adapterType);
const auto typeItB = std::find(PreferredTypeOrder.begin(), PreferredTypeOrder.end(), propertiesB.adapterType);
if (typeItA == PreferredTypeOrder.end() && typeItB != PreferredTypeOrder.end()) {
return -1;
}
return static_cast<int>(typeItA - typeItB);
});
const auto adapterIt = std::find_if(adapters.begin(), adapters.end(), [=](const auto& adapter) -> bool {
wgpu::AdapterProperties properties; wgpu::AdapterProperties properties;
adapter.GetProperties(&properties); adapter.GetProperties(&properties);
return properties.backendType == preferredBackendType; return properties.backendType == backendType;
}); });
if (adapterIt == adapters.end()) { if (adapterIt == adapters.end()) {
Log.report(logvisor::Fatal, FMT_STRING("Failed to find usable graphics backend")); return false;
unreachable();
} }
g_Adapter = *adapterIt; g_Adapter = *adapterIt;
} }
@ -276,9 +304,13 @@ void initialize(SDL_Window* window) {
: supportedLimits.limits.minStorageBufferOffsetAlignment, : supportedLimits.limits.minStorageBufferOffsetAlignment,
}, },
}; };
const std::array<wgpu::FeatureName, 1> requiredFeatures{ std::vector<wgpu::FeatureName> features;
wgpu::FeatureName::TextureCompressionBC, const auto supportedFeatures = g_Adapter.GetSupportedFeatures();
}; for (const auto* const feature : supportedFeatures) {
if (strcmp(feature, "texture-compression-bc") == 0) {
features.push_back(wgpu::FeatureName::TextureCompressionBC);
}
}
const std::array enableToggles { const std::array enableToggles {
/* clang-format off */ /* clang-format off */
#if _WIN32 #if _WIN32
@ -297,11 +329,18 @@ void initialize(SDL_Window* window) {
togglesDescriptor.forceEnabledToggles = enableToggles.data(); togglesDescriptor.forceEnabledToggles = enableToggles.data();
const auto deviceDescriptor = wgpu::DeviceDescriptor{ const auto deviceDescriptor = wgpu::DeviceDescriptor{
.nextInChain = &togglesDescriptor, .nextInChain = &togglesDescriptor,
.requiredFeaturesCount = requiredFeatures.size(), .requiredFeaturesCount = static_cast<uint32_t>(features.size()),
.requiredFeatures = requiredFeatures.data(), .requiredFeatures = features.data(),
.requiredLimits = &requiredLimits, .requiredLimits = &requiredLimits,
}; };
g_device = wgpu::Device::Acquire(g_Adapter.CreateDevice(&deviceDescriptor)); bool deviceCallbackReceived = false;
g_Adapter.RequestDevice(&deviceDescriptor, &device_callback, &deviceCallbackReceived);
// while (!deviceCallbackReceived) {
// TODO wgpuInstanceProcessEvents
// }
if (!g_device) {
return false;
}
g_device.SetUncapturedErrorCallback(&error_callback, nullptr); g_device.SetUncapturedErrorCallback(&error_callback, nullptr);
} }
g_queue = g_device.GetQueue(); g_queue = g_device.GetQueue();
@ -309,8 +348,7 @@ void initialize(SDL_Window* window) {
g_BackendBinding = g_BackendBinding =
std::unique_ptr<utils::BackendBinding>(utils::CreateBinding(g_backendType, window, g_device.Get())); std::unique_ptr<utils::BackendBinding>(utils::CreateBinding(g_backendType, window, g_device.Get()));
if (!g_BackendBinding) { if (!g_BackendBinding) {
Log.report(logvisor::Fatal, FMT_STRING("Unsupported backend {}"), backendName); return false;
unreachable();
} }
auto swapChainFormat = static_cast<wgpu::TextureFormat>(g_BackendBinding->GetPreferredSwapChainTextureFormat()); auto swapChainFormat = static_cast<wgpu::TextureFormat>(g_BackendBinding->GetPreferredSwapChainTextureFormat());
@ -341,9 +379,13 @@ void initialize(SDL_Window* window) {
resize_swapchain(size.fb_width, size.fb_height); resize_swapchain(size.fb_width, size.fb_height);
g_windowSize = size; g_windowSize = size;
} }
return true;
} }
void shutdown() { void shutdown() {
g_CopyBindGroupLayout = {};
g_CopyPipeline = {};
g_CopyBindGroup = {};
g_frameBuffer = {}; g_frameBuffer = {};
g_frameBufferResolved = {}; g_frameBufferResolved = {};
g_depthBuffer = {}; g_depthBuffer = {};

View File

@ -31,15 +31,24 @@ struct TextureWithSampler {
wgpu::Sampler sampler; wgpu::Sampler sampler;
}; };
constexpr std::array PreferredBackendOrder{
#ifdef DAWN_ENABLE_BACKEND_D3D12 #ifdef DAWN_ENABLE_BACKEND_D3D12
static const wgpu::BackendType preferredBackendType = wgpu::BackendType::D3D12; wgpu::BackendType::D3D12,
#elif DAWN_ENABLE_BACKEND_VULKAN
static const wgpu::BackendType preferredBackendType = wgpu::BackendType::Vulkan;
#elif DAWN_ENABLE_BACKEND_METAL
static const wgpu::BackendType preferredBackendType = wgpu::BackendType::Metal;
#else
static const wgpu::BackendType preferredBackendType = wgpu::BackendType::OpenGL;
#endif #endif
#ifdef DAWN_ENABLE_BACKEND_METAL
wgpu::BackendType::Metal,
#endif
#ifdef DAWN_ENABLE_BACKEND_VULKAN
wgpu::BackendType::Vulkan,
#endif
#ifdef DAWN_ENABLE_BACKEND_DESKTOP_GL
wgpu::BackendType::OpenGL,
#endif
#ifdef DAWN_ENABLE_BACKEND_OPENGLES
wgpu::BackendType::OpenGLES,
#endif
};
extern wgpu::Device g_device; extern wgpu::Device g_device;
extern wgpu::Queue g_queue; extern wgpu::Queue g_queue;
extern wgpu::SwapChain g_swapChain; extern wgpu::SwapChain g_swapChain;
@ -51,7 +60,7 @@ extern TextureWithSampler g_depthBuffer;
extern wgpu::RenderPipeline g_CopyPipeline; extern wgpu::RenderPipeline g_CopyPipeline;
extern wgpu::BindGroup g_CopyBindGroup; extern wgpu::BindGroup g_CopyBindGroup;
void initialize(SDL_Window* window); bool initialize(SDL_Window* window, wgpu::BackendType backendType);
void shutdown(); void shutdown();
void resize_swapchain(uint32_t width, uint32_t height); void resize_swapchain(uint32_t width, uint32_t height);
TextureWithSampler create_render_texture(bool multisampled); TextureWithSampler create_render_texture(bool multisampled);

View File

@ -98,6 +98,7 @@ if (NOT MSVC)
target_compile_options(SDL2-static PRIVATE -Wno-implicit-fallthrough -Wno-shadow) target_compile_options(SDL2-static PRIVATE -Wno-implicit-fallthrough -Wno-shadow)
endif () endif ()
set(DAWN_ENABLE_VULKAN ON CACHE BOOL "Enable compilation of the Vulkan backend" FORCE)
add_subdirectory(../extern/dawn dawn EXCLUDE_FROM_ALL) add_subdirectory(../extern/dawn dawn EXCLUDE_FROM_ALL)
if (DAWN_ENABLE_VULKAN) if (DAWN_ENABLE_VULKAN)
target_compile_definitions(dawn_native PRIVATE target_compile_definitions(dawn_native PRIVATE