mirror of https://github.com/AxioDL/metaforce.git
Initial fog volume rendering implementation
This commit is contained in:
parent
0f6ae9d217
commit
2d093b6d80
|
@ -9,8 +9,12 @@
|
||||||
#include "Particle/CElementGen.hpp"
|
#include "Particle/CElementGen.hpp"
|
||||||
#include "CMetroidModelInstance.hpp"
|
#include "CMetroidModelInstance.hpp"
|
||||||
#include "Collision/CAreaOctTree.hpp"
|
#include "Collision/CAreaOctTree.hpp"
|
||||||
|
#include "zeus/CUnitVector.hpp"
|
||||||
|
#include "Graphics/CSkinnedModel.hpp"
|
||||||
|
|
||||||
#define FOGVOL_RAMP_RES 256
|
#define FOGVOL_RAMP_RES 256
|
||||||
|
#define FOGVOL_FAR 750.0
|
||||||
|
#define FOGVOL_NEAR 0.2
|
||||||
#define SPHERE_RAMP_RES 32
|
#define SPHERE_RAMP_RES 32
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
|
@ -268,42 +272,160 @@ void CBooRenderer::HandleUnsortedModel(CAreaListItem* item, CBooModel& model)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct FogVolumeControl
|
||||||
|
{
|
||||||
|
|
||||||
|
u32 xfc_[12][2] =
|
||||||
|
{
|
||||||
|
{0, 1},
|
||||||
|
{1, 3},
|
||||||
|
{3, 2},
|
||||||
|
{2, 0},
|
||||||
|
{4, 5},
|
||||||
|
{5, 7},
|
||||||
|
{7, 6},
|
||||||
|
{6, 4},
|
||||||
|
{0, 4},
|
||||||
|
{1, 5},
|
||||||
|
{3, 7},
|
||||||
|
{2, 6}
|
||||||
|
};
|
||||||
|
u32 x15c_[8] = {};
|
||||||
|
//GXVtxDescList x17c_; {{POS, DIRECT}, {TEX0, DIRECT}}
|
||||||
|
|
||||||
|
} s_FogVolumeCtrl = {};
|
||||||
|
|
||||||
|
void CBooRenderer::DrawFogSlices(const zeus::CPlane* planes, int numPlanes,
|
||||||
|
int iteration, const zeus::CVector3f& center, float delta)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBooRenderer::RenderFogVolumeModel(const zeus::CAABox& aabb, const CModel* model,
|
||||||
|
const zeus::CTransform& modelMtx, const zeus::CTransform& viewMtx,
|
||||||
|
const CSkinnedModel* sModel)
|
||||||
|
{
|
||||||
|
if (!model && !sModel)
|
||||||
|
{
|
||||||
|
zeus::CAABox xfAABB = aabb.getTransformedAABox(modelMtx);
|
||||||
|
zeus::CUnitVector3f viewNormal(viewMtx.basis[1]);
|
||||||
|
zeus::CPlane planes[7] =
|
||||||
|
{
|
||||||
|
{zeus::CVector3f::skRight, xfAABB.min.x},
|
||||||
|
{zeus::CVector3f::skLeft, -xfAABB.max.x},
|
||||||
|
{zeus::CVector3f::skForward, xfAABB.min.y},
|
||||||
|
{zeus::CVector3f::skBack, -xfAABB.max.y},
|
||||||
|
{zeus::CVector3f::skUp, xfAABB.min.z},
|
||||||
|
{zeus::CVector3f::skDown, -xfAABB.max.z},
|
||||||
|
{viewNormal, viewNormal.dot(viewMtx.origin) + 0.2f + 0.1f}
|
||||||
|
};
|
||||||
|
|
||||||
|
CGraphics::SetModelMatrix(zeus::CTransform::Identity());
|
||||||
|
|
||||||
|
float delta = std::max(std::max(
|
||||||
|
xfAABB.max.x - xfAABB.min.x,
|
||||||
|
xfAABB.max.y - xfAABB.min.y),
|
||||||
|
xfAABB.max.z - xfAABB.min.z) * 2.f;
|
||||||
|
|
||||||
|
for (int i=0 ; i<7 ; ++i)
|
||||||
|
DrawFogSlices(planes, 7, i, xfAABB.center(), delta);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CModelFlags flags;
|
||||||
|
flags.m_extendedShaderIdx = 5;
|
||||||
|
if (sModel)
|
||||||
|
{
|
||||||
|
sModel->Draw(flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
model->UpdateLastFrame();
|
||||||
|
model->GetInstance().Draw(flags, nullptr, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CBooRenderer::ReallyRenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb,
|
void CBooRenderer::ReallyRenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb,
|
||||||
const CModel* model, const CSkinnedModel* sModel)
|
const CModel* model, const CSkinnedModel* sModel)
|
||||||
{
|
{
|
||||||
zeus::CTransform backupModel = CGraphics::g_GXModelMatrix;
|
zeus::CTransform backupModel = CGraphics::g_GXModelMatrix;
|
||||||
zeus::CTransform backupView = CGraphics::g_ViewMatrix;
|
zeus::CTransform backupView = CGraphics::g_ViewMatrix;
|
||||||
zeus::CMatrix4f proj = CGraphics::GetPerspectiveProjectionMatrix(false);
|
zeus::CMatrix4f proj = CGraphics::GetPerspectiveProjectionMatrix(false);
|
||||||
zeus::CVector3f points[8];
|
zeus::CVector4f points[8];
|
||||||
float wVals[8];
|
|
||||||
|
|
||||||
for (int i=0 ; i<8 ; ++i)
|
for (int i=0 ; i<8 ; ++i)
|
||||||
{
|
{
|
||||||
zeus::CVector3f pt = backupModel * aabb.getPoint(i);
|
zeus::CVector3f pt = backupModel * aabb.getPoint(i);
|
||||||
zeus::CVector3f xfPt =
|
zeus::CVector3f xfPt = backupView.transposeRotate(pt - backupView.origin);
|
||||||
backupView.transposeRotate(zeus::CVector3f(pt.x - backupModel.basis[1].z,
|
points[i] = proj * zeus::CVector4f(xfPt);
|
||||||
pt.y - backupModel.basis[1].y,
|
|
||||||
pt.z - backupModel.basis[1].x));
|
|
||||||
zeus::CVector4f xfPt4 = proj * zeus::CVector4f(xfPt);
|
|
||||||
points[i] = xfPt4.toVec3f();
|
|
||||||
wVals[i] = xfPt4.w;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Finish
|
zeus::CVector2i vpMax(0, 0);
|
||||||
|
zeus::CVector2i vpMin(g_Viewport.x8_width, g_Viewport.xc_height);
|
||||||
|
|
||||||
|
bool b1 = true;
|
||||||
for (int i=0 ; i<20 ; ++i)
|
for (int i=0 ; i<20 ; ++i)
|
||||||
{
|
{
|
||||||
zeus::CVector3f overW;
|
zeus::CVector3f overW;
|
||||||
if (i < 8)
|
if (i < 8)
|
||||||
{
|
{
|
||||||
overW = points[i] * (1.f / wVals[i]);
|
overW = points[i].toVec3f() * (1.f / points[i].w);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
const zeus::CVector4f& pt1 = points[s_FogVolumeCtrl.xfc_[i-8][0]];
|
||||||
|
const zeus::CVector4f& pt2 = points[s_FogVolumeCtrl.xfc_[i-8][1]];
|
||||||
|
|
||||||
|
bool eq1 = (pt1.z / pt1.w) == 1.f;
|
||||||
|
bool eq2 = (pt2.z / pt2.w) == 1.f;
|
||||||
|
if (eq1 == eq2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float interp = -(pt1.w - 1.f) / (pt2.w - pt1.w);
|
||||||
|
if (interp <= 0.f || interp >= 1.f)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float wRecip = 1.f / (interp * (pt2.w - pt1.w) + pt1.w);
|
||||||
|
zeus::CVector3f pt1_3 = pt1.toVec3f();
|
||||||
|
zeus::CVector3f pt2_3 = pt2.toVec3f();
|
||||||
|
overW = (pt1_3 + interp * (pt2_3 - pt1_3)) * wRecip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overW.z > 1.001f)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int vpX = zeus::clamp(0, int(g_Viewport.x8_width * overW.x * 0.5f + (g_Viewport.x8_width / 2)), int(g_Viewport.x8_width));
|
||||||
|
int vpY = zeus::clamp(0, int(g_Viewport.xc_height * overW.y * 0.5f + (g_Viewport.xc_height / 2)), int(g_Viewport.xc_height));
|
||||||
|
vpMax.x = std::max(vpMax.x, vpX);
|
||||||
|
vpMin.x = std::min(vpMin.x, vpX);
|
||||||
|
vpMax.y = std::max(vpMax.y, vpY);
|
||||||
|
vpMin.y = std::min(vpMin.y, vpY);
|
||||||
|
b1 = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
zeus::CVector2i vpSize = {320, 228};
|
||||||
|
if (!b1)
|
||||||
|
{
|
||||||
|
vpSize.x = std::min(320, vpMax.x - vpMin.x);
|
||||||
|
vpSize.y = std::min(320, vpMax.y - vpMin.y);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vpSize.x <= 0 || vpSize.y <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//vpMin.y + g_Viewport.x4_top;
|
||||||
|
|
||||||
|
zeus::CAABox box((backupModel * aabb.min) - 1.f, (backupModel * aabb.max) + 1.f);
|
||||||
|
if (box.pointInside(CGraphics::g_ViewPoint) && (model || sModel))
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBooRenderer::GenerateFogVolumeRampTex(boo::IGraphicsDataFactory::Context& ctx)
|
void CBooRenderer::GenerateFogVolumeRampTex(boo::IGraphicsDataFactory::Context& ctx)
|
||||||
|
@ -314,7 +436,9 @@ void CBooRenderer::GenerateFogVolumeRampTex(boo::IGraphicsDataFactory::Context&
|
||||||
for (int x=0 ; x<FOGVOL_RAMP_RES ; ++x)
|
for (int x=0 ; x<FOGVOL_RAMP_RES ; ++x)
|
||||||
{
|
{
|
||||||
int tmp = y << 16 | x << 8 | 0x7f;
|
int tmp = y << 16 | x << 8 | 0x7f;
|
||||||
double a = zeus::clamp(0.0, (-150.0 / (tmp * 749.7998 - 750.0) - 0.2) * 3.0 / 749.7998, 1.0);
|
double a = zeus::clamp(0.0, (-150.0 / (tmp / double(0xffffff) *
|
||||||
|
(FOGVOL_FAR - FOGVOL_NEAR) - FOGVOL_FAR) - FOGVOL_NEAR) * 3.0 /
|
||||||
|
(FOGVOL_FAR - FOGVOL_NEAR), 1.0);
|
||||||
data[y][x] = (a * a + a) / 2.f * 255;
|
data[y][x] = (a * a + a) / 2.f * 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -737,6 +861,7 @@ void CBooRenderer::DrawThermalModel(const CModel& model, const zeus::CColor& mul
|
||||||
flags.m_extendedShaderIdx = 2;
|
flags.m_extendedShaderIdx = 2;
|
||||||
flags.color = mulCol;
|
flags.color = mulCol;
|
||||||
flags.addColor = addCol;
|
flags.addColor = addCol;
|
||||||
|
model.UpdateLastFrame();
|
||||||
model.Draw(flags);
|
model.Draw(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "CPVSVisSet.hpp"
|
#include "CPVSVisSet.hpp"
|
||||||
#include "zeus/CRectangle.hpp"
|
#include "zeus/CRectangle.hpp"
|
||||||
#include "World/CGameArea.hpp"
|
#include "World/CGameArea.hpp"
|
||||||
|
#include "zeus/CPlane.hpp"
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
@ -165,6 +166,10 @@ class CBooRenderer : public IRenderer
|
||||||
void ActivateLightsForModel(CAreaListItem* item, CBooModel& model);
|
void ActivateLightsForModel(CAreaListItem* item, CBooModel& model);
|
||||||
void RenderBucketItems(CAreaListItem* item);
|
void RenderBucketItems(CAreaListItem* item);
|
||||||
void HandleUnsortedModel(CAreaListItem* item, CBooModel& model);
|
void HandleUnsortedModel(CAreaListItem* item, CBooModel& model);
|
||||||
|
static void DrawFogSlices(const zeus::CPlane* planes, int numPlanes, int iteration,
|
||||||
|
const zeus::CVector3f& center, float delta);
|
||||||
|
static void RenderFogVolumeModel(const zeus::CAABox& aabb, const CModel* model, const zeus::CTransform& modelMtx,
|
||||||
|
const zeus::CTransform& viewMtx, const CSkinnedModel* sModel);
|
||||||
void ReallyRenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb,
|
void ReallyRenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb,
|
||||||
const CModel* model, const CSkinnedModel* sModel);
|
const CModel* model, const CSkinnedModel* sModel);
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ SClipScreenRect CGraphics::g_CroppedViewport;
|
||||||
int CGraphics::g_ViewportSamples = 1;
|
int CGraphics::g_ViewportSamples = 1;
|
||||||
bool CGraphics::g_IsGXModelMatrixIdentity = true;
|
bool CGraphics::g_IsGXModelMatrixIdentity = true;
|
||||||
SViewport g_Viewport = {0, 0, 640, 480, 640 / 2.f, 480 / 2.f};
|
SViewport g_Viewport = {0, 0, 640, 480, 640 / 2.f, 480 / 2.f};
|
||||||
|
u32 CGraphics::g_FrameCounter = 0;
|
||||||
|
|
||||||
void CGraphics::DisableAllLights()
|
void CGraphics::DisableAllLights()
|
||||||
{
|
{
|
||||||
|
@ -117,6 +118,8 @@ void CGraphics::EndScene()
|
||||||
|
|
||||||
/* Flush text instance buffers just before GPU command list submission */
|
/* Flush text instance buffers just before GPU command list submission */
|
||||||
CTextSupportShader::UpdateBuffers();
|
CTextSupportShader::UpdateBuffers();
|
||||||
|
|
||||||
|
++g_FrameCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGraphics::SetAlphaCompare(ERglAlphaFunc comp0, u8 ref0, ERglAlphaOp op, ERglAlphaFunc comp1, u8 ref1)
|
void CGraphics::SetAlphaCompare(ERglAlphaFunc comp0, u8 ref0, ERglAlphaOp op, ERglAlphaFunc comp1, u8 ref1)
|
||||||
|
|
|
@ -284,6 +284,8 @@ public:
|
||||||
{g_ExternalTimeProvider = provider;}
|
{g_ExternalTimeProvider = provider;}
|
||||||
static float GetSecondsMod900();
|
static float GetSecondsMod900();
|
||||||
static void TickRenderTimings();
|
static void TickRenderTimings();
|
||||||
|
static u32 g_FrameCounter;
|
||||||
|
static u32 GetFrameCounter() { return g_FrameCounter; }
|
||||||
|
|
||||||
static boo::IGraphicsDataFactory::Platform g_BooPlatform;
|
static boo::IGraphicsDataFactory::Platform g_BooPlatform;
|
||||||
static const boo::SystemChar* g_BooPlatformName;
|
static const boo::SystemChar* g_BooPlatformName;
|
||||||
|
|
|
@ -194,6 +194,7 @@ class CModel
|
||||||
std::unique_ptr<CBooModel> x28_modelInst;
|
std::unique_ptr<CBooModel> x28_modelInst;
|
||||||
CModel* x30_next = nullptr;
|
CModel* x30_next = nullptr;
|
||||||
CModel* x34_prev = nullptr;
|
CModel* x34_prev = nullptr;
|
||||||
|
int x38_lastFrame;
|
||||||
|
|
||||||
/* urde addition: boo! */
|
/* urde addition: boo! */
|
||||||
boo::GraphicsDataToken m_gfxToken;
|
boo::GraphicsDataToken m_gfxToken;
|
||||||
|
@ -217,6 +218,7 @@ public:
|
||||||
CBooModel& GetInstance() {return *x28_modelInst;}
|
CBooModel& GetInstance() {return *x28_modelInst;}
|
||||||
const CBooModel& GetInstance() const {return *x28_modelInst;}
|
const CBooModel& GetInstance() const {return *x28_modelInst;}
|
||||||
std::unique_ptr<CBooModel> MakeNewInstance(int shaderIdx, int subInsts);
|
std::unique_ptr<CBooModel> MakeNewInstance(int shaderIdx, int subInsts);
|
||||||
|
void UpdateLastFrame() const { const_cast<CModel&>(*this).x38_lastFrame = CGraphics::GetFrameCounter(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
CFactoryFnReturn FModelFactory(const urde::SObjectTag& tag,
|
CFactoryFnReturn FModelFactory(const urde::SObjectTag& tag,
|
||||||
|
|
|
@ -764,6 +764,7 @@ std::unique_ptr<CBooModel> CModel::MakeNewInstance(int shaderIdx, int subInsts)
|
||||||
CModel::CModel(std::unique_ptr<u8[]>&& in, u32 /* dataLen */, IObjectStore* store, CObjectReference* selfRef)
|
CModel::CModel(std::unique_ptr<u8[]>&& in, u32 /* dataLen */, IObjectStore* store, CObjectReference* selfRef)
|
||||||
: m_selfToken(selfRef)
|
: m_selfToken(selfRef)
|
||||||
{
|
{
|
||||||
|
x38_lastFrame = CGraphics::GetFrameCounter() - 2;
|
||||||
std::unique_ptr<u8[]> data = std::move(in);
|
std::unique_ptr<u8[]> data = std::move(in);
|
||||||
|
|
||||||
u32 version = hecl::SBig(*reinterpret_cast<u32*>(data.get() + 0x4));
|
u32 version = hecl::SBig(*reinterpret_cast<u32*>(data.get() + 0x4));
|
||||||
|
|
2
specter
2
specter
|
@ -1 +1 @@
|
||||||
Subproject commit de06e0173e9440d75287c0b7431e101fc53e570e
|
Subproject commit 7ea8e20e0310c4f45da0c0c8396b6f6c00a70b85
|
Loading…
Reference in New Issue