Initial fog volume rendering implementation

This commit is contained in:
Jack Andersen 2017-03-09 17:40:24 -10:00
parent 0f6ae9d217
commit 2d093b6d80
7 changed files with 151 additions and 13 deletions

View File

@ -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);
} }

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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,

View File

@ -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));

@ -1 +1 @@
Subproject commit de06e0173e9440d75287c0b7431e101fc53e570e Subproject commit 7ea8e20e0310c4f45da0c0c8396b6f6c00a70b85