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

Player reflection and other imps

This commit is contained in:
Jack Andersen
2017-03-25 19:53:04 -10:00
parent db12dd2ea2
commit c069666307
35 changed files with 654 additions and 72 deletions

View File

@@ -978,6 +978,14 @@ void CBooRenderer::BeginScene()
void CBooRenderer::EndScene()
{
CGraphics::EndScene();
if (x2dc_reflectionAge >= 2)
{
// Delete reflection tex x14c_
}
else
{
++x2dc_reflectionAge;
}
}
void CBooRenderer::SetAmbientColor(const zeus::CColor& color)
@@ -994,6 +1002,24 @@ u32 CBooRenderer::GetFPS()
return 0;
}
void CBooRenderer::CacheReflection(TReflectionCallback cb, void* ctx, bool clearAfter)
{
if (!x318_24_refectionDirty)
return;
x318_24_refectionDirty = false;
x2dc_reflectionAge = 0;
BindReflectionDrawTarget();
SViewport backupVp = g_Viewport;
SetViewport(0, 0, 256, 256);
CGraphics::g_BooMainCommandQueue->clearTarget();
cb(ctx, CBooModel::g_ReflectViewPos);
boo::SWindowRect rect(0, 0, 256, 256);
CGraphics::g_BooMainCommandQueue->resolveBindTexture(x14c_reflectionTex, rect, false, 0, true, false);
BindMainDrawTarget();
SetViewport(backupVp.x0_left, backupVp.x4_top, backupVp.x8_width, backupVp.xc_height);
}
void CBooRenderer::DrawSpaceWarp(const zeus::CVector3f& pt, float strength)
{
m_spaceWarpFilter.setStrength(strength);

View File

@@ -134,6 +134,7 @@ class CBooRenderer : public IRenderer
std::list<CFogVolumeFilter> m_fogVolumeFilters;
std::list<CFogVolumeFilter>::iterator m_nextFogVolumeFilter;
std::list<std::pair<zeus::CVector3f, float>> x2c4_spaceWarps;
u32 x2dc_reflectionAge = 2;
zeus::CColor x2e0_ = zeus::CColor::skWhite;
zeus::CVector3f x2e4_ = {0.f, 1.f, 0.f};
@@ -231,7 +232,7 @@ public:
void SetAmbientColor(const zeus::CColor&);
void DrawString(const char*, int, int);
u32 GetFPS();
//void CacheReflection(TReflectionCallback, void*, bool);
void CacheReflection(TReflectionCallback, void*, bool);
void DrawSpaceWarp(const zeus::CVector3f&, float);
void DrawThermalModel(const CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol);
void DrawXRayOutline(const zeus::CAABox&);

View File

@@ -178,8 +178,11 @@ public:
static void SetDrawingOccluders(bool occ) {g_DrawingOccluders = occ;}
static void SetNewPlayerPositionAndTime(const zeus::CVector3f& pos);
static void KillCachedViewDepState();
static zeus::CVector3f g_ReflectViewPos;
static void KillCachedViewDepState();
static void EnsureViewDepStateCached(const CBooModel& model, const CBooSurface* surf,
zeus::CMatrix4f*& mtxsOut, float& alphaOut);
};
class CModel

View File

@@ -46,6 +46,83 @@ void CBooModel::KillCachedViewDepState()
g_LastModelCached = nullptr;
}
zeus::CVector3f CBooModel::g_ReflectViewPos = {};
static const zeus::CMatrix4f ReflectBaseMtx =
{
0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 1.f,
0.f, 0.f, 0.f, 1.f
};
void CBooModel::EnsureViewDepStateCached(const CBooModel& model, const CBooSurface* surf,
zeus::CMatrix4f*& mtxsOut, float& alphaOut)
{
zeus::CVector3f modelToPlayer = g_PlayerPosition - CGraphics::g_GXModelMatrix.origin;
zeus::CVector3f modelToPlayerLocal = CGraphics::g_GXModelMatrix.transposeRotate(modelToPlayer);
zeus::CVector3f surfPos;
float surfSize = 0.f;
if (surf)
{
zeus::CVector3f surfCenter(surf->m_data.centroid);
zeus::CVector3f surfNormal(surf->m_data.reflectionNormal);
float dotDelta = surfNormal.dot(modelToPlayerLocal) - surfCenter.dot(surfNormal);
surfPos = modelToPlayerLocal - surfNormal * dotDelta;
}
else
{
surfPos = model.x20_aabb.center();
surfSize = (model.x20_aabb.max.x - model.x20_aabb.min.x) + (model.x20_aabb.max.y - model.x20_aabb.min.y) * 0.5f;
}
if (g_Renderer->x318_24_refectionDirty)
{
zeus::CVector3f playerToPos = g_ReflectViewPos - g_PlayerPosition;
zeus::CVector3f vecToPos = surfPos - g_PlayerPosition;
if (playerToPos.dot(playerToPos) < vecToPos.dot(vecToPos))
g_ReflectViewPos = surfPos;
}
else
{
g_ReflectViewPos = surfPos;
g_Renderer->x318_24_refectionDirty = true;
}
zeus::CVector3f playerToSurf = surfPos - modelToPlayerLocal;
float distance = std::max(-(0.5f * surfSize - playerToSurf.magnitude()), FLT_EPSILON);
if (distance >= 5.f)
{
alphaOut = 0.f;
}
else
{
alphaOut = (5.f - distance) / 5.f;
/* Indirect map matrix */
mtxsOut[0] = (CGraphics::g_ViewMatrix.inverse() * CGraphics::g_GXModelMatrix).toMatrix4f();
/* Reflection map matrix */
zeus::CVector3f v1 = playerToSurf * (1.f / surfSize);
zeus::CVector3f v2 = v1.cross(zeus::CVector3f::skUp);
if (v2.canBeNormalized())
v2.normalize();
else
v2 = zeus::CVector3f::skRight;
float timeScale = 0.32258067f * (0.02f * distance + 1.f);
float f1 = timeScale * g_TransformedTime;
float f2 = timeScale * g_TransformedTime2;
mtxsOut[1] = ReflectBaseMtx;
mtxsOut[1][0][0] = f1 * v2.x;
mtxsOut[1][1][0] = f1 * v2.y;
mtxsOut[1][3][0] = -surfPos.dot(v2) * f1 + 0.5f;
mtxsOut[1][2][1] = f2;
mtxsOut[1][3][1] = -modelToPlayerLocal.z * f2;
}
}
CBooModel::~CBooModel()
{
if (m_prev)
@@ -162,11 +239,24 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
uniBufSize += thisSz;
}
/* Surface reflection texmatrix uniform with first identity slot */
size_t reflectOff = uniBufSize;
uniBufSize += 256;
for (const CBooSurface& surf : *x0_surfaces)
{
const MaterialSet::Material& mat = x4_matSet->materials.at(surf.m_data.matIdx);
if (mat.flags.samusReflection() || mat.flags.samusReflectionSurfaceEye())
uniBufSize += 256;
}
/* Allocate resident buffer */
m_uniformDataSize = uniBufSize;
newInst.m_uniformBuffer = ctx.newDynamicBuffer(boo::BufferUse::Uniform, uniBufSize, 1);
boo::IGraphicsBuffer* bufs[] = {newInst.m_uniformBuffer, newInst.m_uniformBuffer, newInst.m_uniformBuffer};
boo::IGraphicsBuffer* bufs[] = {newInst.m_uniformBuffer,
newInst.m_uniformBuffer,
newInst.m_uniformBuffer,
newInst.m_uniformBuffer};
/* Binding for each surface */
newInst.m_shaderDataBindings.reserve(x0_surfaces->size());
@@ -175,14 +265,16 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
boo::ITexture* mbShadowTexs[] = {g_Renderer->m_ballShadowId,
g_Renderer->x220_sphereRamp,
g_Renderer->m_ballFade};
size_t thisOffs[3];
size_t thisSizes[3];
size_t thisOffs[4];
size_t thisSizes[4];
static const boo::PipelineStage stages[3] = {boo::PipelineStage::Vertex,
static const boo::PipelineStage stages[4] = {boo::PipelineStage::Vertex,
boo::PipelineStage::Vertex,
boo::PipelineStage::Fragment};
boo::PipelineStage::Fragment,
boo::PipelineStage::Vertex};
/* Enumerate surfaces and build data bindings */
size_t curReflect = reflectOff + 256;
for (const CBooSurface& surf : *x0_surfaces)
{
const MaterialSet::Material& mat = x4_matSet->materials.at(surf.m_data.matIdx);
@@ -193,6 +285,7 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
TCachedToken<CTexture>& tex = x1c_textures[idx];
texs[texCount++] = tex.GetObj()->GetBooTexture();
}
texs[6] = g_Renderer->x14c_reflectionTex;
texs[7] = g_Renderer->x220_sphereRamp;
if (m_skinBankCount)
@@ -212,6 +305,18 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
thisOffs[2] = lightOff;
thisSizes[2] = lightSz;
bool useReflection = mat.flags.samusReflection() || mat.flags.samusReflectionSurfaceEye();
if (useReflection)
{
thisOffs[3] = curReflect;
curReflect += 256;
}
else
{
thisOffs[3] = reflectOff;
}
thisSizes[3] = 256;
const std::shared_ptr<hecl::Runtime::ShaderPipelines>& pipelines = m_pipelines->at(surf.m_data.matIdx);
newInst.m_shaderDataBindings.emplace_back();
@@ -233,6 +338,11 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
texCount = 3;
ltexs = mbShadowTexs;
}
else if (useReflection)
{
texCount = 7;
ltexs = texs;
}
else
{
texCount = mat.textureIdxs.size();
@@ -240,7 +350,7 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
}
extendeds.push_back(
ctx.newShaderDataBinding(pipeline, m_vtxFmt,
x8_vbo, nullptr, xc_ibo, 3, bufs, stages,
x8_vbo, nullptr, xc_ibo, 4, bufs, stages,
thisOffs, thisSizes, texCount, ltexs, nullptr, nullptr));
++idx;
}
@@ -704,6 +814,26 @@ void CBooModel::UpdateUniformData(const CModelFlags& flags,
lightingOut.fog = CGraphics::g_Fog;
}
dataCur += sizeof(CModelShaders::LightingUniform);
dataCur = dataOut + ROUND_UP_256(dataCur - dataOut);
/* Reflection texmtx uniform */
zeus::CMatrix4f* identMtxs = reinterpret_cast<zeus::CMatrix4f*>(dataCur);
identMtxs[0] = zeus::CMatrix4f();
identMtxs[1] = zeus::CMatrix4f();
u8* curReflect = dataCur + 256;
for (const CBooSurface& surf : *x0_surfaces)
{
const MaterialSet::Material& mat = x4_matSet->materials.at(surf.m_data.matIdx);
if (mat.flags.samusReflection() || mat.flags.samusReflectionSurfaceEye())
{
zeus::CMatrix4f* mtxs = reinterpret_cast<zeus::CMatrix4f*>(curReflect);
float& alpha = reinterpret_cast<float&>(mtxs[2]);
curReflect += 256;
EnsureViewDepStateCached(*this, mat.flags.samusReflectionSurfaceEye() ? &surf : nullptr, mtxs, alpha);
}
}
inst->m_uniformBuffer->unmap();
}
@@ -807,10 +937,17 @@ CModel::CModel(std::unique_ptr<u8[]>&& in, u32 /* dataLen */, IObjectStore* stor
matSet.m_shaders.reserve(matSet.m_matSet.materials.size());
for (const MaterialSet::Material& mat : matSet.m_matSet.materials)
{
hecl::Backend::ReflectionType reflectionType;
if (mat.flags.samusReflectionIndirectTexture())
reflectionType = hecl::Backend::ReflectionType::Indirect;
else if (mat.flags.samusReflection())
reflectionType = hecl::Backend::ReflectionType::Simple;
else
reflectionType = hecl::Backend::ReflectionType::None;
hecl::Runtime::ShaderTag tag(mat.heclIr,
hmdlMeta.colorCount, hmdlMeta.uvCount, hmdlMeta.weightCount,
hmdlMeta.weightCount * 4, 8, boo::Primitive(hmdlMeta.topology),
true, true, true);
reflectionType, true, true, true);
matSet.m_shaders.push_back(CModelShaders::g_ModelShaders->buildExtendedShader
(tag, mat.heclIr, "CMDL", *CGraphics::g_BooFactory));
}

View File

@@ -51,4 +51,7 @@ CMorphableSkinnedModel::CMorphableSkinnedModel(IObjectStore& store, ResId model,
{
}
CSkinnedModel::FPointGenerator CSkinnedModel::g_PointGenFunc = nullptr;
void* CSkinnedModel::g_PointGenCtx = nullptr;
}

View File

@@ -44,6 +44,15 @@ public:
const std::experimental::optional<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes);
void Draw(const CModelFlags& drawFlags) const;
typedef void(*FPointGenerator)(void* item, const zeus::CVector3f* v1, const zeus::CVector3f* v2, int w1);
static void SetPointGeneratorFunc(void* ctx, FPointGenerator func)
{
g_PointGenFunc = func;
g_PointGenCtx = ctx;
}
static FPointGenerator g_PointGenFunc;
static void* g_PointGenCtx;
};
class CMorphableSkinnedModel : public CSkinnedModel

View File

@@ -88,7 +88,7 @@ public:
virtual void SetAmbientColor(const zeus::CColor&)=0;
virtual void DrawString(const char*, int, int)=0;
virtual u32 GetFPS()=0;
//virtual void CacheReflection(TReflectionCallback, void*, bool)=0;
virtual void CacheReflection(TReflectionCallback, void*, bool)=0;
virtual void DrawSpaceWarp(const zeus::CVector3f&, float)=0;
virtual void DrawThermalModel(const CModel&, const zeus::CColor&, const zeus::CColor&)=0;
virtual void DrawXRayOutline(const zeus::CAABox&)=0;