mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-12-08 14:24:56 +00:00
Support for rendering dynamic cubemaps
This commit is contained in:
@@ -705,7 +705,7 @@ void CBooRenderer::EnablePVS(const CPVSVisSet& set, u32 areaIdx) {
|
||||
|
||||
void CBooRenderer::DisablePVS() { xc8_pvs = rstl::nullopt; }
|
||||
|
||||
void CBooRenderer::UpdateAreaUniforms(int areaIdx, bool shadowRender, bool activateLights) {
|
||||
void CBooRenderer::UpdateAreaUniforms(int areaIdx, bool shadowRender, bool activateLights, int cubeFace) {
|
||||
SetupRendererStates();
|
||||
|
||||
CModelFlags flags;
|
||||
@@ -716,7 +716,7 @@ void CBooRenderer::UpdateAreaUniforms(int areaIdx, bool shadowRender, bool activ
|
||||
bufIdx = 1;
|
||||
} else {
|
||||
flags.m_extendedShader = EExtendedShader::Lighting;
|
||||
bufIdx = 0;
|
||||
bufIdx = cubeFace == -1 ? 0 : 2 + cubeFace;
|
||||
}
|
||||
|
||||
for (CAreaListItem& item : x1c_areaListItems) {
|
||||
@@ -724,7 +724,7 @@ void CBooRenderer::UpdateAreaUniforms(int areaIdx, bool shadowRender, bool activ
|
||||
continue;
|
||||
|
||||
item.m_shaderSet->m_geomLayout->Update(flags, nullptr, nullptr, &item.m_shaderSet->m_matSet,
|
||||
item.m_shaderSet->m_geomLayout->m_sharedBuffer[bufIdx], nullptr);
|
||||
item.m_shaderSet->m_geomLayout->GetSharedBuffer(bufIdx), nullptr);
|
||||
|
||||
for (auto it = item.x10_models.begin(); it != item.x10_models.end(); ++it) {
|
||||
CBooModel* model = *it;
|
||||
|
||||
@@ -201,7 +201,7 @@ public:
|
||||
const SShader* shaderSet);
|
||||
void EnablePVS(const CPVSVisSet&, u32);
|
||||
void DisablePVS();
|
||||
void UpdateAreaUniforms(int areaIdx, bool shadowRender = false, bool activateLights = true);
|
||||
void UpdateAreaUniforms(int areaIdx, bool shadowRender = false, bool activateLights = true, int cubeFace = -1);
|
||||
void RemoveStaticGeometry(const std::vector<CMetroidModelInstance>*);
|
||||
void DrawAreaGeometry(int areaIdx, int mask, int targetMask);
|
||||
void DrawUnsortedGeometry(int areaIdx, int mask, int targetMask, bool shadowRender = false);
|
||||
|
||||
@@ -31,6 +31,33 @@ bool CGraphics::g_IsGXModelMatrixIdentity = true;
|
||||
SViewport g_Viewport = {0, 0, 640, 480, 640 / 2.f, 480 / 2.f};
|
||||
u32 CGraphics::g_FrameCounter = 0;
|
||||
|
||||
const zeus::CMatrix3f CGraphics::skCubeBasisMats[] = {
|
||||
/* Right */
|
||||
{0.f, 1.f, 0.f,
|
||||
1.f, 0.f, 0.f,
|
||||
0.f, 0.f, -1.f},
|
||||
/* Left */
|
||||
{0.f, -1.f, 0.f,
|
||||
-1.f, 0.f, 0.f,
|
||||
0.f, 0.f, -1.f},
|
||||
/* Up */
|
||||
{1.f, 0.f, 0.f,
|
||||
0.f, 0.f, -1.f,
|
||||
0.f, 1.f, 0.f},
|
||||
/* Down */
|
||||
{1.f, 0.f, 0.f,
|
||||
0.f, 0.f, 1.f,
|
||||
0.f, -1.f, 0.f},
|
||||
/* Back */
|
||||
{1.f, 0.f, 0.f,
|
||||
0.f, -1.f, 0.f,
|
||||
0.f, 0.f, -1.f},
|
||||
/* Forward */
|
||||
{-1.f, 0.f, 0.f,
|
||||
0.f, 1.f, 0.f,
|
||||
0.f, 0.f, -1.f},
|
||||
};
|
||||
|
||||
void CGraphics::DisableAllLights() {
|
||||
g_NumLightsActive = 0;
|
||||
g_LightActive = ERglLightBits::None;
|
||||
|
||||
@@ -176,6 +176,8 @@ enum class ETexelFormat {
|
||||
#define DEPTH_SCREEN_ACTORS (1.f / 64.f)
|
||||
#define DEPTH_HUD (1.f / 512.f)
|
||||
#define DEPTH_NEAR 0.f
|
||||
#define CUBEMAP_RES 256
|
||||
#define CUBEMAP_MIPS 6
|
||||
|
||||
class CGraphics {
|
||||
public:
|
||||
@@ -268,6 +270,8 @@ public:
|
||||
static boo::IGraphicsCommandQueue* g_BooMainCommandQueue;
|
||||
static boo::ObjToken<boo::ITextureR> g_SpareTexture;
|
||||
|
||||
static const zeus::CMatrix3f skCubeBasisMats[6];
|
||||
|
||||
static void InitializeBoo(boo::IGraphicsDataFactory* factory, boo::IGraphicsCommandQueue* cc,
|
||||
const boo::ObjToken<boo::ITextureR>& spareTex) {
|
||||
g_BooPlatform = factory->platform();
|
||||
|
||||
@@ -77,7 +77,7 @@ struct CBooSurface {
|
||||
using MaterialSet = DataSpec::DNAMP1::HMDLMaterialSet;
|
||||
|
||||
struct GeometryUniformLayout {
|
||||
boo::ObjToken<boo::IGraphicsBufferD> m_sharedBuffer[2];
|
||||
mutable std::vector<boo::ObjToken<boo::IGraphicsBufferD>> m_sharedBuffer;
|
||||
size_t m_geomBufferSize = 0;
|
||||
size_t m_skinBankCount = 0;
|
||||
size_t m_weightVecCount = 0;
|
||||
@@ -92,6 +92,9 @@ struct GeometryUniformLayout {
|
||||
void Update(const CModelFlags& flags, const CSkinRules* cskr, const CPoseAsTransforms* pose,
|
||||
const MaterialSet* matSet, const boo::ObjToken<boo::IGraphicsBufferD>& buf,
|
||||
const CBooModel* parent) const;
|
||||
|
||||
void ReserveSharedBuffers(boo::IGraphicsDataFactory::Context& ctx, int size);
|
||||
boo::ObjToken<boo::IGraphicsBufferD> GetSharedBuffer(int idx) const;
|
||||
};
|
||||
|
||||
struct SShader {
|
||||
@@ -167,6 +170,7 @@ private:
|
||||
|
||||
boo::ObjToken<boo::ITexture> m_lastDrawnShadowMap;
|
||||
boo::ObjToken<boo::ITexture> m_lastDrawnOneTexture;
|
||||
boo::ObjToken<boo::ITextureCubeR> m_lastDrawnReflectionCube;
|
||||
|
||||
ModelInstance* PushNewModelInstance(int sharedLayoutBuf = -1);
|
||||
void DrawAlphaSurfaces(const CModelFlags& flags) const;
|
||||
@@ -240,10 +244,13 @@ public:
|
||||
static boo::ObjToken<boo::ITexture> g_disintegrateTexture;
|
||||
static void SetDisintegrateTexture(const boo::ObjToken<boo::ITexture>& map) { g_disintegrateTexture = map; }
|
||||
|
||||
static boo::ObjToken<boo::ITextureCubeR> g_reflectionCube;
|
||||
static void SetReflectionCube(const boo::ObjToken<boo::ITextureCubeR>& map) { g_reflectionCube = map; }
|
||||
|
||||
static void SetDummyTextures(bool b) { g_DummyTextures = b; }
|
||||
static void SetRenderModelBlack(bool b) { g_RenderModelBlack = b; }
|
||||
|
||||
static void AssertAllFreed();
|
||||
static void Shutdown();
|
||||
|
||||
const zeus::CAABox& GetAABB() const { return x20_aabb; }
|
||||
};
|
||||
|
||||
@@ -18,7 +18,12 @@ bool CBooModel::g_DrawingOccluders = false;
|
||||
|
||||
static CBooModel* g_FirstModel = nullptr;
|
||||
|
||||
void CBooModel::AssertAllFreed() { assert(g_FirstModel == nullptr && "Dangling CBooModels detected"); }
|
||||
void CBooModel::Shutdown() {
|
||||
g_shadowMap.reset();
|
||||
g_disintegrateTexture.reset();
|
||||
g_reflectionCube.reset();
|
||||
assert(g_FirstModel == nullptr && "Dangling CBooModels detected");
|
||||
}
|
||||
|
||||
void CBooModel::ClearModelUniformCounters() {
|
||||
for (CBooModel* model = g_FirstModel; model; model = model->m_next)
|
||||
@@ -123,6 +128,7 @@ void CBooModel::EnsureViewDepStateCached(const CBooModel& model, const CBooSurfa
|
||||
boo::ObjToken<boo::ITexture> CBooModel::g_shadowMap;
|
||||
zeus::CTransform CBooModel::g_shadowTexXf;
|
||||
boo::ObjToken<boo::ITexture> CBooModel::g_disintegrateTexture;
|
||||
boo::ObjToken<boo::ITextureCubeR> CBooModel::g_reflectionCube;
|
||||
|
||||
void CBooModel::EnableShadowMaps(const boo::ObjToken<boo::ITexture>& map, const zeus::CTransform& texXf) {
|
||||
g_shadowMap = map;
|
||||
@@ -248,7 +254,7 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance(int sharedLayoutBuf) {
|
||||
/* Build geometry uniform buffer if shared not available */
|
||||
boo::ObjToken<boo::IGraphicsBufferD> geomUniformBuf;
|
||||
if (sharedLayoutBuf >= 0) {
|
||||
geomUniformBuf = m_geomLayout->m_sharedBuffer[sharedLayoutBuf];
|
||||
geomUniformBuf = m_geomLayout->GetSharedBuffer(sharedLayoutBuf);
|
||||
} else {
|
||||
geomUniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, m_geomLayout->m_geomBufferSize, 1);
|
||||
newInst.m_geomUniformBuffer = geomUniformBuf;
|
||||
@@ -356,7 +362,7 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance(int sharedLayoutBuf) {
|
||||
texs[8] = g_Renderer->m_ballShadowId.get();
|
||||
texs[9] = g_Renderer->x220_sphereRamp.get();
|
||||
texs[10] = g_Renderer->m_ballFade.get();
|
||||
} else if (idx == EExtendedShader::WorldShadow) {
|
||||
} else if (idx == EExtendedShader::WorldShadow || idx == EExtendedShader::LightingCubeReflectionWorldShadow) {
|
||||
if (g_shadowMap)
|
||||
texs[8] = g_shadowMap;
|
||||
else
|
||||
@@ -366,6 +372,12 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance(int sharedLayoutBuf) {
|
||||
texs[8] = g_disintegrateTexture;
|
||||
else
|
||||
texs[8] = g_Renderer->x220_sphereRamp.get();
|
||||
} else if (idx == EExtendedShader::LightingCubeReflection ||
|
||||
idx == EExtendedShader::LightingCubeReflectionWorldShadow) {
|
||||
if (m_lastDrawnReflectionCube)
|
||||
texs[11] = m_lastDrawnReflectionCube.get();
|
||||
else
|
||||
texs[11] = g_Renderer->x220_sphereRamp.get();
|
||||
}
|
||||
extendeds.push_back(ctx.newShaderDataBinding(pipeline, newInst.GetBooVBO(*this, ctx), nullptr,
|
||||
m_staticIbo.get(), 4, bufs, stages, thisOffs, thisSizes, 12, texs,
|
||||
@@ -778,7 +790,8 @@ void CBooModel::UVAnimationBuffer::Update(u8*& bufOut, const MaterialSet* matSet
|
||||
postMtxOut[1].y() = 0.5f;
|
||||
postMtxOut[3].x() = 0.5f;
|
||||
postMtxOut[3].y() = 0.5f;
|
||||
} else if (flags.m_extendedShader == EExtendedShader::WorldShadow) {
|
||||
} else if (flags.m_extendedShader == EExtendedShader::WorldShadow ||
|
||||
flags.m_extendedShader == EExtendedShader::LightingCubeReflectionWorldShadow) {
|
||||
/* Special matrix for mapping world shadow */
|
||||
specialMtxOut.emplace();
|
||||
|
||||
@@ -891,6 +904,31 @@ void GeometryUniformLayout::Update(const CModelFlags& flags, const CSkinRules* c
|
||||
buf->unmap();
|
||||
}
|
||||
|
||||
void GeometryUniformLayout::ReserveSharedBuffers(boo::IGraphicsDataFactory::Context& ctx, int size) {
|
||||
if (m_sharedBuffer.size() < size)
|
||||
m_sharedBuffer.resize(size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
auto& buf = m_sharedBuffer[i];
|
||||
if (!buf)
|
||||
buf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, m_geomBufferSize, 1);
|
||||
}
|
||||
}
|
||||
|
||||
boo::ObjToken<boo::IGraphicsBufferD> GeometryUniformLayout::GetSharedBuffer(int idx) const {
|
||||
if (idx >= m_sharedBuffer.size())
|
||||
m_sharedBuffer.resize(idx + 1);
|
||||
|
||||
auto& buf = m_sharedBuffer[idx];
|
||||
if (!buf) {
|
||||
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
|
||||
buf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, m_geomBufferSize, 1);
|
||||
return true;
|
||||
} BooTrace);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
boo::ObjToken<boo::IGraphicsBufferD> CBooModel::UpdateUniformData(const CModelFlags& flags, const CSkinRules* cskr,
|
||||
const CPoseAsTransforms* pose,
|
||||
int sharedLayoutBuf) const {
|
||||
@@ -898,7 +936,9 @@ boo::ObjToken<boo::IGraphicsBufferD> CBooModel::UpdateUniformData(const CModelFl
|
||||
return {};
|
||||
|
||||
/* Invalidate instances if new shadow being drawn */
|
||||
if (flags.m_extendedShader == EExtendedShader::WorldShadow && m_lastDrawnShadowMap != g_shadowMap) {
|
||||
if ((flags.m_extendedShader == EExtendedShader::WorldShadow ||
|
||||
flags.m_extendedShader == EExtendedShader::LightingCubeReflectionWorldShadow) &&
|
||||
m_lastDrawnShadowMap != g_shadowMap) {
|
||||
const_cast<CBooModel*>(this)->m_lastDrawnShadowMap = g_shadowMap;
|
||||
const_cast<CBooModel*>(this)->m_instances.clear();
|
||||
}
|
||||
@@ -909,6 +949,14 @@ boo::ObjToken<boo::IGraphicsBufferD> CBooModel::UpdateUniformData(const CModelFl
|
||||
const_cast<CBooModel*>(this)->m_instances.clear();
|
||||
}
|
||||
|
||||
/* Invalidate instances if new reflection cube being drawn */
|
||||
if ((flags.m_extendedShader == EExtendedShader::LightingCubeReflection ||
|
||||
flags.m_extendedShader == EExtendedShader::LightingCubeReflectionWorldShadow) &&
|
||||
m_lastDrawnReflectionCube != g_reflectionCube) {
|
||||
const_cast<CBooModel*>(this)->m_lastDrawnReflectionCube = g_reflectionCube;
|
||||
const_cast<CBooModel*>(this)->m_instances.clear();
|
||||
}
|
||||
|
||||
const ModelInstance* inst;
|
||||
if (sharedLayoutBuf >= 0) {
|
||||
if (m_instances.size() <= sharedLayoutBuf) {
|
||||
|
||||
@@ -145,7 +145,13 @@ static hecl::Backend::ExtensionSlot g_ExtensionSlots[] = {
|
||||
false, false, true, false, false, false, true},
|
||||
/* Normal lit shading with alpha */
|
||||
{0, nullptr, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original,
|
||||
hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface}};
|
||||
hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface},
|
||||
/* Normal lit shading with cube reflection */
|
||||
{0, nullptr, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original,
|
||||
hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface, false, false, true},
|
||||
/* Normal lit shading with cube reflection and world shadow */
|
||||
{0, nullptr, hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original,
|
||||
hecl::Backend::ZTest::Original, hecl::Backend::CullMode::Backface, false, false, true}};
|
||||
|
||||
static const char* ShaderMacros[] = {
|
||||
"URDE_LIGHTING",
|
||||
@@ -172,6 +178,8 @@ static const char* ShaderMacros[] = {
|
||||
"URDE_LIGHTING",
|
||||
"URDE_THERMAL_COLD",
|
||||
"URDE_LIGHTING",
|
||||
"URDE_LIGHTING_CUBE_REFLECTION",
|
||||
"URDE_LIGHTING_CUBE_REFLECTION_SHADOW",
|
||||
};
|
||||
|
||||
void CModelShaders::Initialize() {
|
||||
|
||||
@@ -38,6 +38,8 @@ enum EExtendedShader : uint8_t {
|
||||
ForcedAdditiveNoZWriteDepthGreater,
|
||||
ThermalCold,
|
||||
LightingAlphaWrite,
|
||||
LightingCubeReflection,
|
||||
LightingCubeReflectionWorldShadow,
|
||||
MAX
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user