2
0
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:
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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -38,6 +38,8 @@ enum EExtendedShader : uint8_t {
ForcedAdditiveNoZWriteDepthGreater,
ThermalCold,
LightingAlphaWrite,
LightingCubeReflection,
LightingCubeReflectionWorldShadow,
MAX
};