2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-09 09:47:43 +00:00

Support for rendering dynamic cubemaps

This commit is contained in:
Jack Andersen
2019-05-31 17:41:01 -10:00
parent 486c925a45
commit 410d7896f7
23 changed files with 372 additions and 54 deletions

View File

@@ -603,6 +603,25 @@ zeus::CFrustum CStateManager::SetupViewForDraw(const SViewport& vp) const {
return frustum;
}
zeus::CFrustum CStateManager::SetupViewForCubeFaceDraw(const zeus::CVector3f& pos, int face) const {
zeus::CTransform mainCamXf = x870_cameraManager->GetCurrentCameraTransform(*this);
zeus::CTransform camXf = zeus::CTransform(mainCamXf.basis * CGraphics::skCubeBasisMats[face], pos);
g_Renderer->SetWorldViewpoint(camXf);
CBooModel::SetNewPlayerPositionAndTime(x84c_player->GetTranslation());
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,
const zeus::CTransform& backupViewMatrix) const {
g_Renderer->SetViewport(backupViewport.x0_left, backupViewport.x4_top, backupViewport.x8_width,
@@ -621,14 +640,17 @@ void CStateManager::ResetViewAfterDraw(const SViewport& backupViewport,
void CStateManager::DrawWorld() const {
CTimeProvider timeProvider(xf14_curTimeMod900);
SViewport backupViewport = g_Viewport;
zeus::CFrustum frustum = SetupViewForDraw(g_Viewport);
zeus::CTransform backupViewMatrix = CGraphics::g_ViewMatrix;
/* Area camera is in (not necessarily player) */
TAreaId visAreaId = GetVisAreaId();
x850_world->TouchSky();
DrawWorldCubeFaces();
zeus::CFrustum frustum = SetupViewForDraw(g_Viewport);
zeus::CTransform backupViewMatrix = CGraphics::g_ViewMatrix;
int areaCount = 0;
const CGameArea* areaArr[10];
for (const CGameArea& area : *x850_world) {
@@ -851,6 +873,107 @@ void CStateManager::DrawWorld() const {
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;
TAreaId visAreaId = actor.GetAreaIdAlways();
SViewport backupVp = g_Viewport;
int areaCount = 0;
const CGameArea* areaArr[10];
for (const CGameArea& area : *x850_world) {
if (areaCount == 10)
break;
CGameArea::EOcclusionState 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) {
CGraphics::g_BooMainCommandQueue->setRenderTarget(actor.m_reflectionCube, f);
SetupViewForCubeFaceDraw(actor.GetRenderBounds().center(), f);
CGraphics::g_BooMainCommandQueue->clearTarget();
std::sort(std::begin(areaArr), std::begin(areaArr) + 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;
CPVSVisSet pvsArr[10];
for (const CGameArea** area = areaArr; area != areaArr + 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, false, 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 {
int areaCount = 0;
const CGameArea* areaArr[10];
for (const CGameArea& area : *x850_world) {
if (areaCount == 10)
break;
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded;
if (area.IsPostConstructed())
occState = area.GetOcclusionState();
if (occState == CGameArea::EOcclusionState::Visible)
areaArr[areaCount++] = &area;
}
for (int ai = 0; ai < areaCount; ++ai) {
const CGameArea& area = *areaArr[ai];
int cubeInst = 0;
for (CEntity* ent : *area.GetAreaObjects()) {
if (TCastToPtr<CActor> actor = ent)
DrawActorCubeFaces(*actor, cubeInst);
}
}
}
void CStateManager::SetupFogForArea(TAreaId area) const {
if (area == kInvalidAreaId)
area = x8cc_nextAreaId;