diff --git a/Runtime/AutoMapper/CAutoMapper.cpp b/Runtime/AutoMapper/CAutoMapper.cpp index 9250c752a..5daf97279 100644 --- a/Runtime/AutoMapper/CAutoMapper.cpp +++ b/Runtime/AutoMapper/CAutoMapper.cpp @@ -42,9 +42,15 @@ void CAutoMapper::SAutoMapperRenderState::InterpolateWithClamp(const SAutoMapper { float easeB = eases[int(b.x44_viewportEase)]; float easeA = 1.f - easeB; - out.x0_viewportSize = zeus::CVector2i(b.x0_viewportSize.x * easeB + a.x0_viewportSize.x * easeA, - b.x0_viewportSize.y * easeB + a.x0_viewportSize.y * easeA); + zeus::CVector2i vpA = a.m_getViewportSize(); + zeus::CVector2i vpB = b.m_getViewportSize(); + out.x0_viewportSize = zeus::CVector2i(vpB.x * easeB + vpA.x * easeA, + vpB.y * easeB + vpA.y * easeA); } + if (t == 1.f) + out.m_getViewportSize = b.m_getViewportSize; + else + out.m_getViewportSize = nullptr; if (b.x48_camEase != Ease::None) { @@ -468,7 +474,7 @@ CAutoMapper::BuildMiniMapWorldRenderState(const CStateManager& stateMgr, { zeus::CQuaternion camOrient = GetMiniMapCameraOrientation(stateMgr); zeus::CQuaternion useOrient = (camOrient.dot(rot) >= 0.f) ? camOrient : camOrient.buildEquivalent(); - SAutoMapperRenderState ret(GetMiniMapViewportSize(), useOrient, g_tweakAutoMapper->GetMiniCamDist(), + SAutoMapperRenderState ret(GetMiniMapViewportSize, useOrient, g_tweakAutoMapper->GetMiniCamDist(), g_tweakAutoMapper->GetMiniCamAngle(), GetAreaPointOfInterest(stateMgr, area), GetMapAreaMiniMapDrawDepth(), GetMapAreaMiniMapDrawDepth(), GetMapAreaMiniMapDrawAlphaSurfaceVisited(stateMgr), @@ -490,7 +496,7 @@ CAutoMapper::BuildMapScreenWorldRenderState(const CStateManager& mgr, TAreaId area, bool doingHint) const { float camDist = doingHint ? g_tweakAutoMapper->GetMaxCamDist() : g_tweakAutoMapper->GetCamDist(); - SAutoMapperRenderState ret(GetMapScreenViewportSize(), rot, camDist, + SAutoMapperRenderState ret(GetMapScreenViewportSize, rot, camDist, g_tweakAutoMapper->GetCamAngle(), GetAreaPointOfInterest(mgr, area), GetMapAreaMaxDrawDepth(mgr, area), GetMapAreaMaxDrawDepth(mgr, area), @@ -512,7 +518,7 @@ CAutoMapper::BuildMapScreenUniverseRenderState(const CStateManager& mgr, const zeus::CQuaternion& rot, TAreaId area) const { - SAutoMapperRenderState ret(GetMapScreenViewportSize(), rot, g_tweakAutoMapper->GetUniverseCamDist(), + SAutoMapperRenderState ret(GetMapScreenViewportSize, rot, g_tweakAutoMapper->GetUniverseCamDist(), g_tweakAutoMapper->GetCamAngle(), GetAreaPointOfInterest(mgr, area), GetMapAreaMaxDrawDepth(mgr, area), GetMapAreaMaxDrawDepth(mgr, area), @@ -1203,6 +1209,7 @@ void CAutoMapper::Update(float dt, const CStateManager& mgr) if (!m_frmeInitialized && x28_frmeMapScreen.IsLoaded()) { + x28_frmeMapScreen->SetMaxAspect(1.78f); m_frmeInitialized = true; static_cast(x28_frmeMapScreen->FindWidget("textpane_left"))->TextSupport(). SetText(g_MainStringTable->GetString(42)); @@ -1269,8 +1276,9 @@ void CAutoMapper::Update(float dt, const CStateManager& mgr) if (x30c_basewidget_leftPane) { + float vpAspectRatio = std::max(1.78f, g_Viewport.x8_width / float(g_Viewport.xc_height)); x30c_basewidget_leftPane->SetLocalTransform( - zeus::CTransform::Translate(x318_leftPanePos * -15.f, 0.f, 0.f) * + zeus::CTransform::Translate(x318_leftPanePos * vpAspectRatio * -9.f, 0.f, 0.f) * x30c_basewidget_leftPane->GetTransform()); } @@ -1443,7 +1451,16 @@ void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, flo alphaInterp = 1.f; } - float aspect = xa8_renderStates[0].x0_viewportSize.x / float(xa8_renderStates[0].x0_viewportSize.y); + float aspect; + if (xa8_renderStates[0].m_getViewportSize) + { + zeus::CVector2i vp = xa8_renderStates[0].m_getViewportSize(); + aspect = vp.x / float(vp.y); + } + else + aspect = xa8_renderStates[0].x0_viewportSize.x / float(xa8_renderStates[0].x0_viewportSize.y); + if (aspect > 1.78f) + aspect = 1.78f; float yScale = xa8_renderStates[0].x18_camDist / std::tan(M_PIF / 2.f - 0.5f * 2.f * M_PIF * (xa8_renderStates[0].x1c_camAngle / 360.f)); float xScale = yScale * aspect; diff --git a/Runtime/AutoMapper/CAutoMapper.hpp b/Runtime/AutoMapper/CAutoMapper.hpp index 184e9ae26..88c528b22 100644 --- a/Runtime/AutoMapper/CAutoMapper.hpp +++ b/Runtime/AutoMapper/CAutoMapper.hpp @@ -42,6 +42,8 @@ public: In, InOut }; + typedef zeus::CVector2i(*FGetViewportSize)(); + FGetViewportSize m_getViewportSize; zeus::CVector2i x0_viewportSize; zeus::CQuaternion x8_camOrientation; float x18_camDist; @@ -60,10 +62,10 @@ public: Ease x54_depth2Ease; Ease x58_alphaEase; SAutoMapperRenderState() = default; - SAutoMapperRenderState(const zeus::CVector2i& v1, const zeus::CQuaternion& rot, + SAutoMapperRenderState(FGetViewportSize v1, const zeus::CQuaternion& rot, float f1, float f2, const zeus::CVector3f& v2, float f3, float f4, float f5, float f6, float f7, float f8) - : x0_viewportSize(v1), x8_camOrientation(rot), x18_camDist(f1), x1c_camAngle(f2), + : m_getViewportSize(v1), x0_viewportSize(v1()), x8_camOrientation(rot), x18_camDist(f1), x1c_camAngle(f2), x20_areaPoint(v2), x2c_drawDepth1(f3), x30_drawDepth2(f4), x34_alphaSurfaceVisited(f5), x38_alphaOutlineVisited(f6), x3c_alphaSurfaceUnvisited(f7), x40_alphaOutlineUnvisited(f8), diff --git a/Runtime/Graphics/CBooRenderer.cpp b/Runtime/Graphics/CBooRenderer.cpp index 98060e9d9..56f450f86 100644 --- a/Runtime/Graphics/CBooRenderer.cpp +++ b/Runtime/Graphics/CBooRenderer.cpp @@ -190,9 +190,10 @@ CBooRenderer::CAreaListItem::CAreaListItem (const std::vector* geom, const CAreaRenderOctTree* octTree, std::vector>&& textures, - std::vector&& models, int areaIdx) + std::vector&& models, int areaIdx, + const SShader* shaderSet) : x0_geometry(geom), x4_octTree(octTree), x8_textures(std::move(textures)), - x10_models(std::move(models)), x18_areaIdx(areaIdx) {} + x10_models(std::move(models)), x18_areaIdx(areaIdx), m_shaderSet(shaderSet) {} CBooRenderer::CAreaListItem::~CAreaListItem() {} @@ -738,7 +739,7 @@ void CBooRenderer::AddWorldSurfaces(CBooModel& model) CBooSurface* surf = model.x3c_firstSortedSurface; while (surf) { - const CBooModel::MaterialSet::Material& mat = model.GetMaterialByIndex(surf->m_data.matIdx); + const MaterialSet::Material& mat = model.GetMaterialByIndex(surf->m_data.matIdx); zeus::CAABox aabb = surf->GetBounds(); zeus::CVector3f pt = aabb.closestPointAlongVector(xb0_viewPlane.vec); Buckets::Insert(pt, aabb, EDrawableType::WorldSurface, surf, xb0_viewPlane, @@ -755,7 +756,8 @@ CBooRenderer::FindStaticGeometry(const std::vector* geome } void CBooRenderer::AddStaticGeometry(const std::vector* geometry, - const CAreaRenderOctTree* octTree, int areaIdx) + const CAreaRenderOctTree* octTree, int areaIdx, + const SShader* shaderSet) { auto search = FindStaticGeometry(geometry); if (search == x1c_areaListItems.end()) @@ -773,7 +775,7 @@ void CBooRenderer::AddStaticGeometry(const std::vector* g models.back()->x44_areaInstanceIdx = instIdx++; } } - x1c_areaListItems.emplace_back(geometry, octTree, std::move(textures), std::move(models), areaIdx); + x1c_areaListItems.emplace_back(geometry, octTree, std::move(textures), std::move(models), areaIdx, shaderSet); } } @@ -792,19 +794,23 @@ void CBooRenderer::UpdateAreaUniforms(int areaIdx) { SetupRendererStates(); + CModelFlags flags; + flags.m_extendedShader = EExtendedShader::Lighting; + for (CAreaListItem& item : x1c_areaListItems) { if (areaIdx != -1 && item.x18_areaIdx != areaIdx) continue; + item.m_shaderSet->m_geomLayout->Update(flags, nullptr, nullptr, &item.m_shaderSet->m_matSet, + item.m_shaderSet->m_geomLayout->m_sharedBuffer); + for (auto it = item.x10_models.begin(); it != item.x10_models.end(); ++it) { CBooModel* model = *it; if (model->TryLockTextures()) { ActivateLightsForModel(&item, *model); - CModelFlags flags; - flags.m_extendedShader = EExtendedShader::Lighting; model->UpdateUniformData(flags, nullptr, nullptr); } } diff --git a/Runtime/Graphics/CBooRenderer.hpp b/Runtime/Graphics/CBooRenderer.hpp index 2dbeb14df..b26116256 100644 --- a/Runtime/Graphics/CBooRenderer.hpp +++ b/Runtime/Graphics/CBooRenderer.hpp @@ -68,11 +68,13 @@ class CBooRenderer : public IRenderer int x18_areaIdx; /* Per-area octree-word major, light bits minor */ std::vector x1c_lightOctreeWords; + const SShader* m_shaderSet; CAreaListItem(const std::vector* geom, const CAreaRenderOctTree* octTree, std::vector>&& textures, - std::vector&& models, int areaIdx); + std::vector&& models, int areaIdx, + const SShader* shaderSet); ~CAreaListItem(); }; @@ -205,7 +207,8 @@ public: void AddWorldSurfaces(CBooModel& model); std::list::iterator FindStaticGeometry(const std::vector*); - void AddStaticGeometry(const std::vector*, const CAreaRenderOctTree*, int areaIdx); + void AddStaticGeometry(const std::vector*, const CAreaRenderOctTree*, int areaIdx, + const SShader* shaderSet); void EnablePVS(const CPVSVisSet&, u32); void DisablePVS(); void UpdateAreaUniforms(int areaIdx); diff --git a/Runtime/Graphics/CModel.hpp b/Runtime/Graphics/CModel.hpp index 8f550ae54..1c2ac0c28 100644 --- a/Runtime/Graphics/CModel.hpp +++ b/Runtime/Graphics/CModel.hpp @@ -70,6 +70,44 @@ struct CBooSurface } }; +using MaterialSet = DataSpec::DNAMP1::HMDLMaterialSet; +using UVAnimation = DataSpec::DNAMP1::MaterialSet::Material::UVAnimation; + +struct GeometryUniformLayout +{ + boo::ObjToken m_sharedBuffer; + size_t m_geomBufferSize = 0; + size_t m_skinBankCount = 0; + size_t m_weightVecCount = 0; + + std::vector m_skinOffs; + std::vector m_skinSizes; + + std::vector m_uvOffs; + std::vector m_uvSizes; + + GeometryUniformLayout(const CModel* model, const MaterialSet* matSet); + void Update(const CModelFlags& flags, const CSkinRules* cskr, const CPoseAsTransforms* pose, + const MaterialSet* matSet, const boo::ObjToken& buf) const; +}; + +struct SShader +{ + std::vector> x0_textures; + std::vector> m_shaders; + MaterialSet m_matSet; + std::experimental::optional m_geomLayout; + int m_matSetIdx; + SShader(int idx) : m_matSetIdx(idx) {} + void InitializeLayout(const CModel* model) { m_geomLayout.emplace(model, &m_matSet); } + void UnlockTextures(); + std::shared_ptr + BuildShader(const hecl::HMDLMeta& meta, const MaterialSet::Material& mat); + void BuildShaders(const hecl::HMDLMeta& meta, + std::vector>& shaders); + void BuildShaders(const hecl::HMDLMeta& meta) { BuildShaders(meta, m_shaders); } +}; + class CBooModel { friend class CModel; @@ -77,24 +115,8 @@ class CBooModel friend class CBooRenderer; friend class CMetroidModelInstance; friend class CSkinnedModel; + friend struct GeometryUniformLayout; public: - using MaterialSet = DataSpec::DNAMP1::HMDLMaterialSet; - using UVAnimation = DataSpec::DNAMP1::MaterialSet::Material::UVAnimation; - struct SShader - { - std::vector> x0_textures; - std::vector> m_shaders; - MaterialSet m_matSet; - int m_matSetIdx; - SShader(int idx) : m_matSetIdx(idx) {} - void UnlockTextures(); - std::shared_ptr - BuildShader(const hecl::HMDLMeta& meta, const MaterialSet::Material& mat); - void BuildShaders(const hecl::HMDLMeta& meta, - std::vector>& shaders); - void BuildShaders(const hecl::HMDLMeta& meta) { BuildShaders(meta, m_shaders); } - }; - enum class ESurfaceSelection { UnsortedOnly, @@ -110,6 +132,7 @@ private: CModel* m_model; std::vector* x0_surfaces; const MaterialSet* x4_matSet; + const GeometryUniformLayout* m_geomLayout; int m_matSetIdx = -1; const std::vector>* m_pipelines; std::vector> x1c_textures; @@ -134,6 +157,7 @@ private: size_t m_uniformDataSize = 0; struct ModelInstance { + boo::ObjToken m_geomUniformBuffer; boo::ObjToken m_uniformBuffer; std::vector>> m_shaderDataBindings; boo::ObjToken m_dynamicVtxFmt; @@ -233,19 +257,20 @@ public: static void EnableShadowMaps(const boo::ObjToken& map, const zeus::CTransform& texXf); static void DisableShadowMaps(); - static void SetDummyTextures(bool b) { g_DummyTextures = true; } + static void SetDummyTextures(bool b) { g_DummyTextures = b; } }; class CModel { friend class CBooModel; + friend struct GeometryUniformLayout; //std::unique_ptr x0_data; //u32 x4_dataLen; TToken m_selfToken; /* DO NOT LOCK! */ zeus::CAABox m_aabb; u32 m_flags; std::vector x8_surfaces; - std::vector x18_matSets; + std::vector x18_matSets; std::unique_ptr x28_modelInst; CModel* x30_next = nullptr; CModel* x34_prev = nullptr; diff --git a/Runtime/Graphics/CModelBoo.cpp b/Runtime/Graphics/CModelBoo.cpp index 373a4f119..7ab1573b4 100644 --- a/Runtime/Graphics/CModelBoo.cpp +++ b/Runtime/Graphics/CModelBoo.cpp @@ -153,9 +153,9 @@ CBooModel::CBooModel(TToken& token, CModel* parent, std::vector& ibo, const zeus::CAABox& aabb, u8 renderMask, int numInsts, const boo::ObjToken txtrOverrides[8]) : m_modelTok(token), m_model(parent), x0_surfaces(surfaces), x4_matSet(&shader.m_matSet), - m_matSetIdx(shader.m_matSetIdx), m_pipelines(&shader.m_shaders), x1c_textures(shader.x0_textures), - x20_aabb(aabb), x40_24_texturesLoaded(false), x40_25_modelVisible(0), x41_mask(renderMask), - m_staticVtxFmt(vtxFmt), m_staticVbo(vbo), m_staticIbo(ibo) + m_geomLayout(&*shader.m_geomLayout), m_matSetIdx(shader.m_matSetIdx), m_pipelines(&shader.m_shaders), + x1c_textures(shader.x0_textures), x20_aabb(aabb), x40_24_texturesLoaded(false), x40_25_modelVisible(0), + x41_mask(renderMask), m_staticVtxFmt(vtxFmt), m_staticVbo(vbo), m_staticIbo(ibo) { if (txtrOverrides) for (int i=0 ; i<8 ; ++i) @@ -226,6 +226,50 @@ CBooModel::ModelInstance::GetBooVtxFmt(const CBooModel& model, return m_dynamicVtxFmt; } +GeometryUniformLayout::GeometryUniformLayout(const CModel* model, const MaterialSet* matSet) +{ + if (model) + { + m_skinBankCount = model->m_hmdlMeta.bankCount; + m_weightVecCount = model->m_hmdlMeta.weightCount; + } + + m_skinOffs.reserve(std::max(size_t(1), m_skinBankCount)); + m_skinSizes.reserve(std::max(size_t(1), m_skinBankCount)); + + m_uvOffs.reserve(matSet->materials.size()); + m_uvSizes.reserve(matSet->materials.size()); + + if (m_skinBankCount) + { + /* Skinned */ + for (size_t i=0 ; imaterials) + { + size_t thisSz = ROUND_UP_256(/*mat.uvAnims.size()*/ 8 * (sizeof(zeus::CMatrix4f) * 2)); + m_uvOffs.push_back(m_geomBufferSize); + m_uvSizes.push_back(thisSz); + m_geomBufferSize += thisSz; + } +} + CBooModel::ModelInstance* CBooModel::PushNewModelInstance() { if (!x40_24_texturesLoaded && !g_DummyTextures) @@ -235,58 +279,21 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance() Log.report(logvisor::Fatal, "Model buffer overflow"); m_instances.emplace_back(); ModelInstance& newInst = m_instances.back(); - size_t skinBankCount = 0; - size_t weightVecCount = 0; - if (const CModel* model = m_model) - { - skinBankCount = model->m_hmdlMeta.bankCount; - weightVecCount = model->m_hmdlMeta.weightCount; - } CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool { - /* Determine space required by uniform buffer */ - std::vector skinOffs; - std::vector skinSizes; - skinOffs.reserve(std::max(size_t(1), skinBankCount)); - skinSizes.reserve(std::max(size_t(1), skinBankCount)); - - std::vector uvOffs; - std::vector uvSizes; - uvOffs.reserve(x4_matSet->materials.size()); - uvSizes.reserve(x4_matSet->materials.size()); - - /* Vert transform matrices */ - size_t uniBufSize = 0; - if (skinBankCount) - { - /* Skinned */ - for (size_t i=0 ; i geomUniformBuf; + if (m_geomLayout->m_sharedBuffer) + geomUniformBuf = m_geomLayout->m_sharedBuffer; else { - /* Non-Skinned */ - size_t thisSz = ROUND_UP_256(sizeof(zeus::CMatrix4f) * 3); - skinOffs.push_back(uniBufSize); - skinSizes.push_back(thisSz); - uniBufSize += thisSz; + geomUniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, m_geomLayout->m_geomBufferSize, 1); + newInst.m_geomUniformBuffer = geomUniformBuf; } - /* Animated UV transform matrices */ - size_t matCount = x4_matSet->materials.size(); - for (const MaterialSet::Material& mat : x4_matSet->materials) - { - size_t thisSz = ROUND_UP_256(/*mat.uvAnims.size()*/ 8 * (sizeof(zeus::CMatrix4f) * 2)); - uvOffs.push_back(uniBufSize); - uvSizes.push_back(thisSz); - uniBufSize += thisSz; - } + /* Lighting and reflection uniforms */ + size_t uniBufSize = 0; /* Lighting uniform */ size_t lightOff = 0; @@ -312,8 +319,8 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance() m_uniformDataSize = uniBufSize; newInst.m_uniformBuffer = ctx.newDynamicBuffer(boo::BufferUse::Uniform, uniBufSize, 1); - boo::ObjToken bufs[] = {newInst.m_uniformBuffer.get(), - newInst.m_uniformBuffer.get(), + boo::ObjToken bufs[] = {geomUniformBuf.get(), + geomUniformBuf.get(), newInst.m_uniformBuffer.get(), newInst.m_uniformBuffer.get()}; @@ -369,10 +376,10 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance() } } - if (skinBankCount) + if (m_geomLayout->m_skinBankCount) { - thisOffs[0] = skinOffs[surf.m_data.skinMtxBankIdx]; - thisSizes[0] = skinSizes[surf.m_data.skinMtxBankIdx]; + thisOffs[0] = m_geomLayout->m_skinOffs[surf.m_data.skinMtxBankIdx]; + thisSizes[0] = m_geomLayout->m_skinSizes[surf.m_data.skinMtxBankIdx]; } else { @@ -380,8 +387,8 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance() thisSizes[0] = 256; } - thisOffs[1] = uvOffs[surf.m_data.matIdx]; - thisSizes[1] = uvSizes[surf.m_data.matIdx]; + thisOffs[1] = m_geomLayout->m_uvOffs[surf.m_data.matIdx]; + thisSizes[1] = m_geomLayout->m_uvSizes[surf.m_data.matIdx]; thisOffs[2] = lightOff; thisSizes[2] = lightSz; @@ -486,6 +493,7 @@ void CBooModel::DisableAllLights() void CBooModel::RemapMaterialData(SShader& shader) { x4_matSet = &shader.m_matSet; + m_geomLayout = &*shader.m_geomLayout; m_matSetIdx = shader.m_matSetIdx; x1c_textures = shader.x0_textures; m_pipelines = &shader.m_shaders; @@ -497,6 +505,7 @@ void CBooModel::RemapMaterialData(SShader& shader, const std::vector>& pipelines) { x4_matSet = &shader.m_matSet; + m_geomLayout = &*shader.m_geomLayout; m_matSetIdx = shader.m_matSetIdx; x1c_textures = shader.x0_textures; m_pipelines = &pipelines; @@ -844,47 +853,22 @@ void CBooModel::UVAnimationBuffer::Update(u8*& bufOut, const MaterialSet* matSet } } -boo::ObjToken CBooModel::UpdateUniformData(const CModelFlags& flags, - const CSkinRules* cskr, - const CPoseAsTransforms* pose) const +void GeometryUniformLayout::Update(const CModelFlags& flags, + const CSkinRules* cskr, + const CPoseAsTransforms* pose, + const MaterialSet* matSet, + const boo::ObjToken& buf) const { - size_t skinBankCount = 0; - size_t weightVecCount = 0; - if (const CModel* model = m_model) - { - skinBankCount = model->m_hmdlMeta.bankCount; - weightVecCount = model->m_hmdlMeta.weightCount; - } - - /* Invalidate instances if new shadow being drawn */ - if (flags.m_extendedShader == EExtendedShader::WorldShadow && - m_lastDrawnShadowMap != g_shadowMap) - { - const_cast(this)->m_lastDrawnShadowMap = g_shadowMap; - const_cast(this)->m_instances.clear(); - } - - const ModelInstance* inst; - if (m_instances.size() <= m_uniUpdateCount) - { - inst = const_cast(this)->PushNewModelInstance(); - if (!inst) - return nullptr; - } - else - inst = &m_instances[m_uniUpdateCount]; - ++const_cast(this)->m_uniUpdateCount; - - u8* dataOut = reinterpret_cast(inst->m_uniformBuffer->map(m_uniformDataSize)); + u8* dataOut = reinterpret_cast(buf->map(m_geomBufferSize)); u8* dataCur = dataOut; - if (skinBankCount) + if (m_skinBankCount) { /* Skinned */ std::vector bankTransforms; - size_t weightCount = weightVecCount * 4; + size_t weightCount = m_weightVecCount * 4; bankTransforms.reserve(weightCount); - for (size_t i=0 ; i CBooModel::UpdateUniformData(const CModelFl dataCur = dataOut + ROUND_UP_256(dataCur - dataOut); } - UVAnimationBuffer::Update(dataCur, x4_matSet, flags); + CBooModel::UVAnimationBuffer::Update(dataCur, matSet, flags); + buf->unmap(); +} + +boo::ObjToken CBooModel::UpdateUniformData(const CModelFlags& flags, + const CSkinRules* cskr, + const CPoseAsTransforms* pose) const +{ + /* Invalidate instances if new shadow being drawn */ + if (flags.m_extendedShader == EExtendedShader::WorldShadow && + m_lastDrawnShadowMap != g_shadowMap) + { + const_cast(this)->m_lastDrawnShadowMap = g_shadowMap; + const_cast(this)->m_instances.clear(); + } + + const ModelInstance* inst; + if (m_instances.size() <= m_uniUpdateCount) + { + inst = const_cast(this)->PushNewModelInstance(); + if (!inst) + return nullptr; + } + else + inst = &m_instances[m_uniUpdateCount]; + ++const_cast(this)->m_uniUpdateCount; + + if (inst->m_geomUniformBuffer) + m_geomLayout->Update(flags, cskr, pose, x4_matSet, inst->m_geomUniformBuffer); + + u8* dataOut = reinterpret_cast(inst->m_uniformBuffer->map(m_uniformDataSize)); + u8* dataCur = dataOut; if (flags.m_extendedShader == EExtendedShader::Thermal) /* Thermal Model (same as UV Mode 0) */ { @@ -1073,7 +1088,7 @@ std::unique_ptr CModel::MakeNewInstance(int shaderIdx, int subInsts, } std::shared_ptr -CBooModel::SShader::BuildShader(const hecl::HMDLMeta& meta, const MaterialSet::Material& mat) +SShader::BuildShader(const hecl::HMDLMeta& meta, const MaterialSet::Material& mat) { hecl::Backend::ReflectionType reflectionType; if (mat.flags.samusReflectionIndirectTexture()) @@ -1090,8 +1105,8 @@ CBooModel::SShader::BuildShader(const hecl::HMDLMeta& meta, const MaterialSet::M (tag, mat.heclIr, "CMDL", *CGraphics::g_BooFactory); } -void CBooModel::SShader::BuildShaders(const hecl::HMDLMeta& meta, - std::vector>& shaders) +void SShader::BuildShaders(const hecl::HMDLMeta& meta, + std::vector>& shaders) { shaders.reserve(m_matSet.materials.size()); for (const MaterialSet::Material& mat : m_matSet.materials) @@ -1119,7 +1134,7 @@ CModel::CModel(std::unique_ptr&& in, u32 /* dataLen */, IObjectStore* stor u32 matSetSz = hecl::SBig(*secSizeCur); const u8* sec = MemoryFromPartData(dataCur, secSizeCur); x18_matSets.emplace_back(i); - CBooModel::SShader& shader = x18_matSets.back(); + SShader& shader = x18_matSets.back(); athena::io::MemoryReader r(sec, matSetSz); shader.m_matSet.read(r); CBooModel::MakeTexturesFromMats(shader.m_matSet, shader.x0_textures, *store); @@ -1136,8 +1151,11 @@ CModel::CModel(std::unique_ptr&& in, u32 /* dataLen */, IObjectStore* stor const u8* iboData = MemoryFromPartData(dataCur, secSizeCur); const u8* surfInfo = MemoryFromPartData(dataCur, secSizeCur); - for (CBooModel::SShader& matSet : x18_matSets) + for (SShader& matSet : x18_matSets) + { + matSet.InitializeLayout(this); matSet.BuildShaders(m_hmdlMeta); + } CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool { @@ -1186,7 +1204,7 @@ CModel::CModel(std::unique_ptr&& in, u32 /* dataLen */, IObjectStore* stor x28_modelInst = MakeNewInstance(0, 1, nullptr, false); } -void CBooModel::SShader::UnlockTextures() +void SShader::UnlockTextures() { for (TCachedToken& tex : x0_textures) tex.Unlock(); @@ -1289,7 +1307,7 @@ void CModel::_WarmupShaders() CGraphics::SetViewPointMatrix(zeus::CTransform::Translate(0.f, -2048.f, 0.f)); CGraphics::SetOrtho(-2048.f, 2048.f, 2048.f, -2048.f, 0.f, 4096.f); CModelFlags defaultFlags; - for (CBooModel::SShader& shader : x18_matSets) + for (SShader& shader : x18_matSets) { GetInstance().RemapMaterialData(shader); GetInstance().UpdateUniformData(defaultFlags, nullptr, nullptr); diff --git a/Runtime/Graphics/IRenderer.hpp b/Runtime/Graphics/IRenderer.hpp index 7da7069a1..61141de5f 100644 --- a/Runtime/Graphics/IRenderer.hpp +++ b/Runtime/Graphics/IRenderer.hpp @@ -18,6 +18,7 @@ class CLight; class CAreaOctTree; class CParticleGen; class CModel; +class SShader; class CSkinnedModel; class CPVSVisSet; struct CAreaRenderOctTree; @@ -44,7 +45,8 @@ public: }; virtual ~IRenderer() = default; - virtual void AddStaticGeometry(const std::vector*, const CAreaRenderOctTree*, int)=0; + virtual void AddStaticGeometry(const std::vector*, const CAreaRenderOctTree*, int, + const SShader*)=0; virtual void EnablePVS(const CPVSVisSet&, u32)=0; virtual void DisablePVS()=0; virtual void RemoveStaticGeometry(const std::vector*)=0; diff --git a/Runtime/GuiSys/CGuiFrame.cpp b/Runtime/GuiSys/CGuiFrame.cpp index c3da46778..2ce9c8722 100644 --- a/Runtime/GuiSys/CGuiFrame.cpp +++ b/Runtime/GuiSys/CGuiFrame.cpp @@ -148,6 +148,12 @@ void CGuiFrame::SetAspectConstraint(float c) CGuiSys::ViewportResizeFrame(this); } +void CGuiFrame::SetMaxAspect(float c) +{ + m_maxAspect = c; + CGuiSys::ViewportResizeFrame(this); +} + void CGuiFrame::Update(float dt) { xc_headWidget->Update(dt); diff --git a/Runtime/GuiSys/CGuiFrame.hpp b/Runtime/GuiSys/CGuiFrame.hpp index 231ebc905..1f0172d4a 100644 --- a/Runtime/GuiSys/CGuiFrame.hpp +++ b/Runtime/GuiSys/CGuiFrame.hpp @@ -40,6 +40,7 @@ private: zeus::CTransform m_aspectTransform; float m_aspectConstraint = -1.f; + float m_maxAspect = -1.f; public: CGuiFrame(CAssetId id, CGuiSys& sys, int a, int b, int c, CSimplePool* sp); @@ -65,6 +66,7 @@ public: void Touch() const; const zeus::CTransform& GetAspectTransform() const { return m_aspectTransform; } void SetAspectConstraint(float c); + void SetMaxAspect(float c); void Update(float dt); void Draw(const CGuiWidgetDrawParms& parms) const; diff --git a/Runtime/GuiSys/CGuiSys.cpp b/Runtime/GuiSys/CGuiSys.cpp index 9d92b6025..712424275 100644 --- a/Runtime/GuiSys/CGuiSys.cpp +++ b/Runtime/GuiSys/CGuiSys.cpp @@ -93,6 +93,13 @@ void CGuiSys::ViewportResizeFrame(CGuiFrame* frame) } frame->m_aspectTransform = zeus::CTransform::Scale({hPad, 1.f, vPad}); } + else if (frame->m_maxAspect > 0.f) + { + if (vpAspectRatio > frame->m_maxAspect) + frame->m_aspectTransform = zeus::CTransform::Scale({frame->m_maxAspect / vpAspectRatio, 1.f, 1.f}); + else + frame->m_aspectTransform = zeus::CTransform::Identity(); + } } } diff --git a/Runtime/MP1/CSamusHud.cpp b/Runtime/MP1/CSamusHud.cpp index b8d99fa85..5d9048e55 100644 --- a/Runtime/MP1/CSamusHud.cpp +++ b/Runtime/MP1/CSamusHud.cpp @@ -48,7 +48,9 @@ CSamusHud::CSamusHud(CStateManager& stateMgr) x72c_camZTweaks[i] = 0.5f * i - 8.f; x264_loadedFrmeHelmet = x258_frmeHelmet.GetObj(); + x264_loadedFrmeHelmet->SetMaxAspect(1.78f); x274_loadedFrmeBaseHud = x268_frmeBaseHud.GetObj(); + x274_loadedFrmeBaseHud->SetMaxAspect(1.78f); x2a0_helmetIntf = std::make_unique(*x264_loadedFrmeHelmet); rstl::prereserved_vector hasVisors = BuildPlayerHasVisors(stateMgr); @@ -1690,6 +1692,7 @@ void CSamusHud::UpdateStateTransition(float dt, const CStateManager& mgr) if (!x278_selectedHud.IsLoaded() || !x278_selectedHud->GetIsFinishedLoading()) return; x288_loadedSelectedHud = x278_selectedHud.GetObj(); + x288_loadedSelectedHud->SetMaxAspect(1.78f); x2b8_curState = x2bc_nextState; x2bc_nextState = x2c0_setState; InitializeFrameGlueMutable(mgr); diff --git a/Runtime/World/CGameArea.cpp b/Runtime/World/CGameArea.cpp index d6d19c1c8..083401d01 100644 --- a/Runtime/World/CGameArea.cpp +++ b/Runtime/World/CGameArea.cpp @@ -777,7 +777,7 @@ void CGameArea::AddStaticGeometry() g_Renderer->AddStaticGeometry(&x12c_postConstructed->x4c_insts, x12c_postConstructed->xc_octTree ? &*x12c_postConstructed->xc_octTree : nullptr, - x4_selfIdx); + x4_selfIdx, &x12c_postConstructed->m_materialSet); } } @@ -1196,18 +1196,23 @@ void CGameArea::FillInStaticGeometry(bool textures) inst.Clear(); /* Materials */ - CBooModel::SShader& matSet = x12c_postConstructed->m_materialSet; + SShader& matSet = x12c_postConstructed->m_materialSet; auto secIt = m_resolvedBufs.begin() + 2; { athena::io::MemoryReader r(secIt->first, secIt->second); matSet.m_matSet.read(r); if (textures) CBooModel::MakeTexturesFromMats(matSet.m_matSet, matSet.x0_textures, *g_SimplePool); + matSet.InitializeLayout(nullptr); ++secIt; } CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool { + /* Shared geometry uniform buffer */ + matSet.m_geomLayout->m_sharedBuffer = + ctx.newDynamicBuffer(boo::BufferUse::Uniform, matSet.m_geomLayout->m_geomBufferSize, 1); + /* Models */ for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts) { diff --git a/Runtime/World/CGameArea.hpp b/Runtime/World/CGameArea.hpp index d829b73c9..79a53b6e0 100644 --- a/Runtime/World/CGameArea.hpp +++ b/Runtime/World/CGameArea.hpp @@ -213,7 +213,7 @@ public: u32 x8_collisionSize = 0; std::experimental::optional xc_octTree; std::vector x4c_insts; - CBooModel::SShader m_materialSet = {0}; + SShader m_materialSet = {0}; //std::unique_ptr x5c_; std::vector x60_lightsA; std::vector x70_gfxLightsA; diff --git a/hecl b/hecl index 5f21d6081..6ec84b0a4 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 5f21d60814dcd2dbb5d58db7e78b5efb04435c39 +Subproject commit 6ec84b0a45831d673dbd3b3e039a5eb287fd37f3