Work on CMorphBallShadow

This commit is contained in:
Jack Andersen 2017-03-04 21:57:12 -10:00
parent 52fe795407
commit 8ef9ed2c3b
23 changed files with 509 additions and 132 deletions

View File

@ -295,6 +295,14 @@ void CBooRenderer::LoadThermoPalette()
x288_thermoPalette = thermoTexObj->GetPaletteTexture(); x288_thermoPalette = thermoTexObj->GetPaletteTexture();
} }
void CBooRenderer::LoadBallFade()
{
m_ballFadeTex = xc_store.GetObj("TXTR_BallFade");
CTexture* ballFadeTexObj = m_ballFadeTex.GetObj();
if (ballFadeTexObj)
m_ballFade = ballFadeTexObj->GetBooTexture();
}
CBooRenderer::CBooRenderer(IObjectStore& store, IFactory& resFac) CBooRenderer::CBooRenderer(IObjectStore& store, IFactory& resFac)
: x8_factory(resFac), xc_store(store), x2a8_thermalRand(20) : x8_factory(resFac), xc_store(store), x2a8_thermalRand(20)
{ {
@ -305,9 +313,11 @@ CBooRenderer::CBooRenderer(IObjectStore& store, IFactory& resFac)
{ {
GenerateFogVolumeRampTex(ctx); GenerateFogVolumeRampTex(ctx);
GenerateSphereRampTex(ctx); GenerateSphereRampTex(ctx);
m_ballShadowId = ctx.newRenderTexture(m_ballShadowIdW, m_ballShadowIdH, true, false);
return true; return true;
}); });
LoadThermoPalette(); LoadThermoPalette();
LoadBallFade();
m_thermHotFilter.emplace(); m_thermHotFilter.emplace();
Buckets::Init(); Buckets::Init();
@ -732,4 +742,91 @@ void CBooRenderer::SetWorldLightFadeLevel(float level)
x2fc_tevReg1Color = zeus::CColor(level, level, level, 1.f); x2fc_tevReg1Color = zeus::CColor(level, level, level, 1.f);
} }
void CBooRenderer::FindOverlappingWorldModels(std::vector<u32>& modelBits, const zeus::CAABox& aabb) const
{
u32 bitmapWords = 0;
for (const CAreaListItem& item : x1c_areaListItems)
if (item.x4_octTree)
bitmapWords += item.x4_octTree->x14_bitmapWordCount;
if (!bitmapWords)
{
modelBits.clear();
return;
}
modelBits.clear();
modelBits.resize(bitmapWords);
u32 curWord = 0;
for (const CAreaListItem& item : x1c_areaListItems)
{
if (!item.x4_octTree)
continue;
item.x4_octTree->FindOverlappingModels(modelBits.data() + curWord, aabb);
u32 wordModel = 0;
for (int i=0 ; i<item.x4_octTree->x14_bitmapWordCount ; ++i, wordModel += 32)
{
u32& word = modelBits[i];
if (!word)
continue;
for (int j=0 ; j<32 ; ++j)
{
if ((1 << j) & word)
{
const zeus::CAABox& modelAABB = item.x10_models[wordModel + j]->x20_aabb;
if (!modelAABB.intersects(aabb))
word &= ~(1 << j);
}
}
}
curWord += item.x4_octTree->x14_bitmapWordCount;
}
}
int CBooRenderer::DrawOverlappingWorldModelIDs(int alphaVal, const std::vector<u32>& modelBits,
const zeus::CAABox& aabb) const
{
CModelFlags flags(0, 0, 3, zeus::CColor{1.f, 1.f, 1.f, alphaVal / 255.f});
flags.m_extendedShaderIdx = 5; // Do solid color draw
u32 curWord = 0;
for (const CAreaListItem& item : x1c_areaListItems)
{
if (!item.x4_octTree)
continue;
u32 wordModel = 0;
for (int i=0 ; i<item.x4_octTree->x14_bitmapWordCount ; ++i, wordModel += 32)
{
const u32& word = modelBits[i];
if (!word)
continue;
for (int j=0 ; j<32 ; ++j)
{
if ((1 << j) & word)
{
if (alphaVal > 255)
return alphaVal;
const CBooModel& model = *item.x10_models[wordModel + j];
const_cast<CBooModel&>(model).VerifyCurrentShader(0);
for (const CBooSurface* surf = model.x38_firstUnsortedSurface; surf; surf = surf->m_next)
if (surf->GetBounds().intersects(aabb))
model.DrawSurface(*surf, flags);
alphaVal += 4;
flags.color.a = alphaVal / 255.f;
}
}
}
curWord += item.x4_octTree->x14_bitmapWordCount;
}
return alphaVal;
}
} }

View File

@ -99,6 +99,11 @@ class CBooRenderer : public IRenderer
boo::ITextureS* x220_sphereRamp = nullptr; boo::ITextureS* x220_sphereRamp = nullptr;
TLockedToken<CTexture> m_thermoPaletteTex; TLockedToken<CTexture> m_thermoPaletteTex;
boo::ITexture* x288_thermoPalette = nullptr; boo::ITexture* x288_thermoPalette = nullptr;
TLockedToken<CTexture> m_ballFadeTex;
boo::ITexture* m_ballFade = nullptr;
boo::ITextureR* m_ballShadowId = nullptr;
int m_ballShadowIdW = 64;
int m_ballShadowIdH = 64;
CRandom16 x2a8_thermalRand; CRandom16 x2a8_thermalRand;
std::list<u32> x2b8_; std::list<u32> x2b8_;
@ -136,6 +141,7 @@ class CBooRenderer : public IRenderer
void GenerateFogVolumeRampTex(boo::IGraphicsDataFactory::Context& ctx); void GenerateFogVolumeRampTex(boo::IGraphicsDataFactory::Context& ctx);
void GenerateSphereRampTex(boo::IGraphicsDataFactory::Context& ctx); void GenerateSphereRampTex(boo::IGraphicsDataFactory::Context& ctx);
void LoadThermoPalette(); void LoadThermoPalette();
void LoadBallFade();
void ActivateLightsForModel(CAreaListItem* item, CBooModel& model); void ActivateLightsForModel(CAreaListItem* item, CBooModel& model);
void RenderBucketItems(CAreaListItem* item); void RenderBucketItems(CAreaListItem* item);
@ -210,6 +216,23 @@ public:
void BindMainDrawTarget() {CGraphics::g_BooMainCommandQueue->setRenderTarget(CGraphics::g_SpareTexture);} void BindMainDrawTarget() {CGraphics::g_BooMainCommandQueue->setRenderTarget(CGraphics::g_SpareTexture);}
void BindReflectionDrawTarget() {CGraphics::g_BooMainCommandQueue->setRenderTarget(x14c_reflectionTex);} void BindReflectionDrawTarget() {CGraphics::g_BooMainCommandQueue->setRenderTarget(x14c_reflectionTex);}
void BindBallShadowIdTarget()
{
CGraphics::g_BooMainCommandQueue->setRenderTarget(m_ballShadowId);
SetViewport(0, 0, m_ballShadowIdW, m_ballShadowIdH);
}
void ResolveBallShadowIdTarget()
{
CGraphics::g_BooMainCommandQueue->resolveBindTexture(m_ballShadowId,
boo::SWindowRect(0, 0,
m_ballShadowIdW,
m_ballShadowIdH),
false, true, false);
}
void FindOverlappingWorldModels(std::vector<u32>& modelBits, const zeus::CAABox& aabb) const;
int DrawOverlappingWorldModelIDs(int alphaVal, const std::vector<u32>& modelBits,
const zeus::CAABox& aabb) const;
}; };
} }

View File

@ -463,7 +463,7 @@ void CGraphics::SetViewportResolution(const zeus::CVector2i& res)
} }
static boo::SWindowRect CachedVP; static boo::SWindowRect CachedVP;
static float CachedDepthRange[2] = {0.f, 1.f}; zeus::CVector2f CGraphics::g_CachedDepthRange = {0.f, 1.f};
void CGraphics::SetViewport(int leftOff, int bottomOff, int width, int height) void CGraphics::SetViewport(int leftOff, int bottomOff, int width, int height)
{ {
@ -471,7 +471,7 @@ void CGraphics::SetViewport(int leftOff, int bottomOff, int width, int height)
CachedVP.location[1] = bottomOff; CachedVP.location[1] = bottomOff;
CachedVP.size[0] = width; CachedVP.size[0] = width;
CachedVP.size[1] = height; CachedVP.size[1] = height;
g_BooMainCommandQueue->setViewport(CachedVP, CachedDepthRange[0], CachedDepthRange[1]); g_BooMainCommandQueue->setViewport(CachedVP, g_CachedDepthRange[0], g_CachedDepthRange[1]);
} }
void CGraphics::SetScissor(int leftOff, int bottomOff, int width, int height) void CGraphics::SetScissor(int leftOff, int bottomOff, int width, int height)
@ -482,9 +482,9 @@ void CGraphics::SetScissor(int leftOff, int bottomOff, int width, int height)
void CGraphics::SetDepthRange(float znear, float zfar) void CGraphics::SetDepthRange(float znear, float zfar)
{ {
CachedDepthRange[0] = znear; g_CachedDepthRange[0] = znear;
CachedDepthRange[1] = zfar; g_CachedDepthRange[1] = zfar;
g_BooMainCommandQueue->setViewport(CachedVP, CachedDepthRange[0], CachedDepthRange[1]); g_BooMainCommandQueue->setViewport(CachedVP, g_CachedDepthRange[0], g_CachedDepthRange[1]);
} }
CTimeProvider* CGraphics::g_ExternalTimeProvider = nullptr; CTimeProvider* CGraphics::g_ExternalTimeProvider = nullptr;

View File

@ -220,6 +220,7 @@ public:
}; };
static CProjectionState g_Proj; static CProjectionState g_Proj;
static zeus::CVector2f g_CachedDepthRange;
static CFogState g_Fog; static CFogState g_Fog;
static float g_ProjAspect; static float g_ProjAspect;
static u32 g_NumLightsActive; static u32 g_NumLightsActive;

View File

@ -126,8 +126,6 @@ private:
void DrawSurfaces(const CModelFlags& flags) const; void DrawSurfaces(const CModelFlags& flags) const;
void DrawSurface(const CBooSurface& surf, const CModelFlags& flags) const; void DrawSurface(const CBooSurface& surf, const CModelFlags& flags) const;
void VerifyCurrentShader(int shaderIdx);
static zeus::CVector3f g_PlayerPosition; static zeus::CVector3f g_PlayerPosition;
static float g_ModSeconds; static float g_ModSeconds;
static float g_TransformedTime; static float g_TransformedTime;
@ -152,6 +150,7 @@ public:
bool TryLockTextures() const; bool TryLockTextures() const;
void UnlockTextures() const; void UnlockTextures() const;
void Touch(int shaderIdx) const; void Touch(int shaderIdx) const;
void VerifyCurrentShader(int shaderIdx);
void UpdateUniformData(const CModelFlags& flags, void UpdateUniformData(const CModelFlags& flags,
const CSkinRules* cskr, const CSkinRules* cskr,
const CPoseAsTransforms* pose) const; const CPoseAsTransforms* pose) const;
@ -178,6 +177,7 @@ public:
static void SetNewPlayerPositionAndTime(const zeus::CVector3f& pos); static void SetNewPlayerPositionAndTime(const zeus::CVector3f& pos);
static void KillCachedViewDepState(); static void KillCachedViewDepState();
}; };
class CModel class CModel

View File

@ -172,6 +172,10 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
newInst.m_shaderDataBindings.reserve(x0_surfaces->size()); newInst.m_shaderDataBindings.reserve(x0_surfaces->size());
std::vector<boo::ITexture*> texs; std::vector<boo::ITexture*> texs;
texs.resize(8);
boo::ITexture* mbShadowTexs[] = {g_Renderer->m_ballShadowId,
g_Renderer->x220_sphereRamp,
g_Renderer->m_ballFade};
size_t thisOffs[3]; size_t thisOffs[3];
size_t thisSizes[3]; size_t thisSizes[3];
@ -185,13 +189,11 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
const MaterialSet::Material& mat = x4_matSet->materials.at(surf.m_data.matIdx); const MaterialSet::Material& mat = x4_matSet->materials.at(surf.m_data.matIdx);
texs.clear(); texs.clear();
texs.reserve(8);
for (atUint32 idx : mat.textureIdxs) for (atUint32 idx : mat.textureIdxs)
{ {
TCachedToken<CTexture>& tex = x1c_textures[idx]; TCachedToken<CTexture>& tex = x1c_textures[idx];
texs.push_back(tex.GetObj()->GetBooTexture()); texs.push_back(tex.GetObj()->GetBooTexture());
} }
texs.resize(8);
texs[7] = g_Renderer->x220_sphereRamp; texs[7] = g_Renderer->x220_sphereRamp;
if (m_skinBankCount) if (m_skinBankCount)
@ -220,11 +222,27 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
int idx = 0; int idx = 0;
for (boo::IShaderPipeline* pipeline : pipelines->m_pipelines) for (boo::IShaderPipeline* pipeline : pipelines->m_pipelines)
{ {
size_t texCount;
boo::ITexture** ltexs;
if (idx == 2)
{
texCount = 8;
ltexs = texs.data();
}
else if (idx == 6)
{
texCount = 3;
ltexs = mbShadowTexs;
}
else
{
texCount = mat.textureIdxs.size();
ltexs = texs.data();
}
extendeds.push_back( extendeds.push_back(
ctx.newShaderDataBinding(pipeline, m_vtxFmt, ctx.newShaderDataBinding(pipeline, m_vtxFmt,
x8_vbo, nullptr, xc_ibo, 3, bufs, stages, x8_vbo, nullptr, xc_ibo, 3, bufs, stages,
thisOffs, thisSizes, (idx == 2) ? 8 : mat.textureIdxs.size(), thisOffs, thisSizes, texCount, ltexs));
texs.data()));
++idx; ++idx;
} }
} }
@ -630,6 +648,18 @@ void CBooModel::UpdateUniformData(const CModelFlags& flags,
thermalOut.mulColor = flags.color; thermalOut.mulColor = flags.color;
thermalOut.addColor = flags.addColor; thermalOut.addColor = flags.addColor;
} }
else if (flags.m_extendedShaderIdx == 5) /* Solid color render */
{
CModelShaders::SolidUniform& solidOut = *reinterpret_cast<CModelShaders::SolidUniform*>(dataCur);
solidOut.solidColor = flags.color;
}
else if (flags.m_extendedShaderIdx == 6) /* MorphBall shadow render */
{
CModelShaders::MBShadowUniform& shadowOut = *reinterpret_cast<CModelShaders::MBShadowUniform*>(dataCur);
shadowOut.shadowUp = CGraphics::g_GXModelView * zeus::CVector3f::skUp;
shadowOut.shadowUp.w = flags.color.a;
shadowOut.shadowId = flags.color.r;
}
else else
{ {
CModelShaders::LightingUniform& lightingOut = *reinterpret_cast<CModelShaders::LightingUniform*>(dataCur); CModelShaders::LightingUniform& lightingOut = *reinterpret_cast<CModelShaders::LightingUniform*>(dataCur);

View File

@ -32,6 +32,13 @@ const hecl::Backend::TextureInfo CModelShaders::ThermalTextures[] =
{hecl::Backend::TexGenSrc::Normal, 7, 0, 7, true} {hecl::Backend::TexGenSrc::Normal, 7, 0, 7, true}
}; };
const hecl::Backend::TextureInfo CModelShaders::BallFadeTextures[] =
{
{hecl::Backend::TexGenSrc::Position, 0, 0, 0, false}, // ID tex
{hecl::Backend::TexGenSrc::Position, 1, 0, 0, false}, // Sphere ramp
{hecl::Backend::TexGenSrc::Position, 2, 0, 1, false} // TXTR_BallFade
};
CModelShaders::CModelShaders(const hecl::Runtime::FileStoreManager& storeMgr, CModelShaders::CModelShaders(const hecl::Runtime::FileStoreManager& storeMgr,
boo::IGraphicsDataFactory* gfxFactory) boo::IGraphicsDataFactory* gfxFactory)
: m_shaderCache(storeMgr, gfxFactory, GetShaderExtensions(gfxFactory->platform())) {} : m_shaderCache(storeMgr, gfxFactory, GetShaderExtensions(gfxFactory->platform())) {}

View File

@ -22,6 +22,7 @@ class CModelShaders
static hecl::Runtime::ShaderCacheExtensions GetShaderExtensionsHLSL(boo::IGraphicsDataFactory::Platform plat); static hecl::Runtime::ShaderCacheExtensions GetShaderExtensionsHLSL(boo::IGraphicsDataFactory::Platform plat);
static hecl::Runtime::ShaderCacheExtensions GetShaderExtensionsMetal(boo::IGraphicsDataFactory::Platform plat); static hecl::Runtime::ShaderCacheExtensions GetShaderExtensionsMetal(boo::IGraphicsDataFactory::Platform plat);
static const hecl::Backend::TextureInfo ThermalTextures[]; static const hecl::Backend::TextureInfo ThermalTextures[];
static const hecl::Backend::TextureInfo BallFadeTextures[];
public: public:
struct Light struct Light
{ {
@ -47,6 +48,17 @@ public:
zeus::CColor addColor; zeus::CColor addColor;
}; };
struct SolidUniform
{
zeus::CColor solidColor;
};
struct MBShadowUniform
{
zeus::CVector4f shadowUp;
float shadowId;
};
static void Initialize(const hecl::Runtime::FileStoreManager& storeMgr, static void Initialize(const hecl::Runtime::FileStoreManager& storeMgr,
boo::IGraphicsDataFactory* gfxFactory); boo::IGraphicsDataFactory* gfxFactory);

View File

@ -72,6 +72,35 @@ static const char* ThermalPostGLSL =
"}\n" "}\n"
"\n"; "\n";
static const char* SolidPostGLSL =
"UBINDING2 uniform SolidUniform\n"
"{\n"
" vec4 solidColor;\n"
"};\n"
"vec4 SolidPostFunc(vec4 colorIn)\n"
"{\n"
" return solidColor;\n"
"}\n"
"\n";
static const char* MBShadowPostGLSL =
"UBINDING2 uniform MBShadowUniform\n"
"{\n"
" vec4 shadowUp;\n"
" float shadowId;\n"
"};\n"
"vec4 MBShadowPostFunc(vec4 colorIn)\n"
"{\n"
" float idTexel = texture(tex0, vtf.extTcgs[0]).a;\n"
" float sphereTexel = texture(tex1, vtf.extTcgs[1]).a;\n"
" float fadeTexel = texture(tex2, vtf.extTcgs[2]).a;\n"
" float val = ((abs(idTexel - shadowId) < 0.001) ?\n"
" (dot(vtf.mvNorm.xyz, shadowUp.xyz) * shadowUp.w) : 0.0) *\n"
" sphereTexel * fadeTexel;\n"
" return vec4(0.0, 0.0, 0.0, val);\n"
"}\n"
"\n";
static const char* BlockNames[] = {HECL_GLSL_VERT_UNIFORM_BLOCK_NAME, static const char* BlockNames[] = {HECL_GLSL_VERT_UNIFORM_BLOCK_NAME,
HECL_GLSL_TEXMTX_UNIFORM_BLOCK_NAME, HECL_GLSL_TEXMTX_UNIFORM_BLOCK_NAME,
"LightingUniform"}; "LightingUniform"};
@ -80,6 +109,14 @@ static const char* ThermalBlockNames[] = {HECL_GLSL_VERT_UNIFORM_BLOCK_NAME,
HECL_GLSL_TEXMTX_UNIFORM_BLOCK_NAME, HECL_GLSL_TEXMTX_UNIFORM_BLOCK_NAME,
"ThermalUniform"}; "ThermalUniform"};
static const char* SolidBlockNames[] = {HECL_GLSL_VERT_UNIFORM_BLOCK_NAME,
HECL_GLSL_TEXMTX_UNIFORM_BLOCK_NAME,
"SolidUniform"};
static const char* MBShadowBlockNames[] = {HECL_GLSL_VERT_UNIFORM_BLOCK_NAME,
HECL_GLSL_TEXMTX_UNIFORM_BLOCK_NAME,
"MBShadowUniform"};
hecl::Runtime::ShaderCacheExtensions hecl::Runtime::ShaderCacheExtensions
CModelShaders::GetShaderExtensionsGLSL(boo::IGraphicsDataFactory::Platform plat) CModelShaders::GetShaderExtensionsGLSL(boo::IGraphicsDataFactory::Platform plat)
{ {
@ -105,6 +142,17 @@ CModelShaders::GetShaderExtensionsGLSL(boo::IGraphicsDataFactory::Platform plat)
3, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::One, 3, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::One,
hecl::Backend::BlendFactor::One); hecl::Backend::BlendFactor::One);
/* Solid shading */
ext.registerExtensionSlot({}, {SolidPostGLSL, "SolidPostFunc"},
3, SolidBlockNames, 0, nullptr, hecl::Backend::BlendFactor::One,
hecl::Backend::BlendFactor::Zero);
/* MorphBall shadow shading */
ext.registerExtensionSlot({}, {MBShadowPostGLSL, "MBShadowPostFunc"},
3, MBShadowBlockNames, 3, BallFadeTextures,
hecl::Backend::BlendFactor::SrcAlpha,
hecl::Backend::BlendFactor::InvSrcAlpha);
return ext; return ext;
} }

View File

@ -71,6 +71,35 @@ static const char* ThermalPostHLSL =
"}\n" "}\n"
"\n"; "\n";
static const char* SolidPostHLSL =
"cbuffer SolidUniform : register(b2)\n"
"{\n"
" float4 solidColor;\n"
"};\n"
"static float4 SolidPostFunc(float4 colorIn)\n"
"{\n"
" return solidColor;\n"
"}\n"
"\n";
static const char* MBShadowPostHLSL =
"cbuffer MBShadowUniform : register(b2)\n"
"{\n"
" float4 shadowUp;\n"
" float shadowId;\n"
"};\n"
"static float4 MBShadowPostFunc(float4 colorIn)\n"
"{\n"
" float idTexel = extTex0.Sample(samp, vtf.extTcgs[0]).a;\n"
" float sphereTexel = extTex1.Sample(samp, vtf.extTcgs[1]).a;\n"
" float fadeTexel = extTex2.Sample(samp, vtf.extTcgs[2]).a;\n"
" float val = ((abs(idTexel - shadowId) < 0.001) ?\n"
" (dot(vtf.mvNorm.xyz, shadowUp.xyz) * shadowUp.w) : 0.0) *\n"
" sphereTexel * fadeTexel;\n"
" return float4(0.0, 0.0, 0.0, val);\n"
"}\n"
"\n";
hecl::Runtime::ShaderCacheExtensions hecl::Runtime::ShaderCacheExtensions
CModelShaders::GetShaderExtensionsHLSL(boo::IGraphicsDataFactory::Platform plat) CModelShaders::GetShaderExtensionsHLSL(boo::IGraphicsDataFactory::Platform plat)
{ {
@ -96,6 +125,17 @@ CModelShaders::GetShaderExtensionsHLSL(boo::IGraphicsDataFactory::Platform plat)
0, nullptr, 0, nullptr, hecl::Backend::BlendFactor::One, 0, nullptr, 0, nullptr, hecl::Backend::BlendFactor::One,
hecl::Backend::BlendFactor::One); hecl::Backend::BlendFactor::One);
/* Solid shading */
ext.registerExtensionSlot({}, {SolidPostHLSL, "SolidPostFunc"},
0, nullptr, 0, nullptr, hecl::Backend::BlendFactor::One,
hecl::Backend::BlendFactor::Zero);
/* Solid shading */
ext.registerExtensionSlot({}, {MBShadowPostHLSL, "MBShadowPostFunc"},
0, nullptr, 3, BallFadeTextures,
hecl::Backend::BlendFactor::SrcAlpha,
hecl::Backend::BlendFactor::InvSrcAlpha);
return ext; return ext;
} }

View File

@ -71,8 +71,40 @@ static const char* ThermalPostMetal =
"}\n" "}\n"
"\n"; "\n";
static const char* SolidPostMetal =
"struct SolidUniform\n"
"{\n"
" float4 solidColor;\n"
"};\n"
"static float4 SolidPostFunc(thread VertToFrag& vtf, constant SolidUniform& lu, float4 colorIn)\n"
"{\n"
" return lu.solidColor;\n"
"}\n"
"\n";
static const char* MBShadowPostMetal =
"UBINDING2 uniform MBShadowUniform\n"
"{\n"
" vec4 shadowUp;\n"
" float shadowId;\n"
"};\n"
"static float4 MBShadowPostFunc(thread VertToFrag& vtf, constant MBShadowUniform& su,\n"
" texture2d<float> tex0, texture2d<float> tex1, texture2d<float> tex2, float4 colorIn)\n"
"{\n"
" float idTexel = tex0.sample(samp, vtf.extTcgs0).a;\n"
" float sphereTexel = tex1.sample(samp, vtf.extTcgs1).a;\n"
" float fadeTexel = tex2.sample(samp, vtf.extTcgs2).a;\n"
" float val = ((fabs(idTexel - su.shadowId) < 0.001) ?\n"
" (dot(vtf.mvNorm.xyz, su.shadowUp.xyz) * su.shadowUp.w) : 0.0) *\n"
" sphereTexel * fadeTexel;\n"
" return float4(0.0, 0.0, 0.0, val);\n"
"}\n"
"\n";
static const char* BlockNames[] = {"LightingUniform"}; static const char* BlockNames[] = {"LightingUniform"};
static const char* ThermalBlockNames[] = {"ThermalUniform"}; static const char* ThermalBlockNames[] = {"ThermalUniform"};
static const char* SolidBlockNames[] = {"SolidUniform"};
static const char* MBShadowBlockNames[] = {"MBShadowUniform"};
hecl::Runtime::ShaderCacheExtensions hecl::Runtime::ShaderCacheExtensions
CModelShaders::GetShaderExtensionsMetal(boo::IGraphicsDataFactory::Platform plat) CModelShaders::GetShaderExtensionsMetal(boo::IGraphicsDataFactory::Platform plat)
@ -99,6 +131,17 @@ CModelShaders::GetShaderExtensionsMetal(boo::IGraphicsDataFactory::Platform plat
1, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::One, 1, BlockNames, 0, nullptr, hecl::Backend::BlendFactor::One,
hecl::Backend::BlendFactor::One); hecl::Backend::BlendFactor::One);
/* Solid shading */
ext.registerExtensionSlot({}, {SolidPostMetal, "SolidPostFunc"},
1, SolidBlockNames, 0, nullptr, hecl::Backend::BlendFactor::One,
hecl::Backend::BlendFactor::Zero);
/* MorphBall shadow shading */
ext.registerExtensionSlot({}, {MBShadowPostMetal, "MBShadowPostFunc"},
1, MBShadowBlockNames, 3, BallFadeTextures,
hecl::Backend::BlendFactor::SrcAlpha,
hecl::Backend::BlendFactor::InvSrcAlpha);
return ext; return ext;
} }

View File

@ -312,4 +312,15 @@ void CActor::SetActorLights(std::unique_ptr<CActorLights> lights)
x90_actorLights = std::move(lights); x90_actorLights = std::move(lights);
xe4_31_lightsDirty = true; xe4_31_lightsDirty = true;
} }
bool CActor::CanDrawStatic() const
{
if (!x30_24_active)
return false;
if (x64_modelData && x64_modelData->HasNormalModel())
return xb4_ <= 4;
return false;
}
} }

View File

@ -161,6 +161,7 @@ public:
void EnsureRendered(const CStateManager&, const zeus::CVector3f&, const zeus::CVector3f&); void EnsureRendered(const CStateManager&, const zeus::CVector3f&, const zeus::CVector3f&);
SAdvancementDeltas UpdateAnimation(float, CStateManager&, bool); SAdvancementDeltas UpdateAnimation(float, CStateManager&, bool);
void SetActorLights(std::unique_ptr<CActorLights>); void SetActorLights(std::unique_ptr<CActorLights>);
bool CanDrawStatic() const;
bool GetE7_29() const { return xe7_29_; } bool GetE7_29() const { return xe7_29_; }
}; };
} }

View File

@ -414,16 +414,6 @@ bool CGameArea::IGetScriptingMemoryAlways() const
return false; return false;
} }
TAreaId CGameArea::IGetAreaId() const
{
return 0;
}
ResId CGameArea::IGetAreaAssetId() const
{
return 0;
}
bool CGameArea::IIsActive() const bool CGameArea::IIsActive() const
{ {
return false; return false;

View File

@ -266,8 +266,9 @@ public:
void SetPauseState(bool paused); void SetPauseState(bool paused);
bool IGetScriptingMemoryAlways() const; bool IGetScriptingMemoryAlways() const;
TAreaId IGetAreaId() const; TAreaId GetAreaId() const { return x4_selfIdx; }
ResId IGetAreaAssetId() const; TAreaId IGetAreaId() const { return x4_selfIdx; }
ResId IGetAreaAssetId() const { return x84_mrea; }
bool IIsActive() const; bool IIsActive() const;
TAreaId IGetAttachedAreaId(int) const; TAreaId IGetAttachedAreaId(int) const;
u32 IGetNumAttachedAreas() const; u32 IGetNumAttachedAreas() const;

View File

@ -8,7 +8,7 @@ set(WORLD_SOURCES
CEnergyDrainSource.hpp CEnergyDrainSource.cpp CEnergyDrainSource.hpp CEnergyDrainSource.cpp
CPlayerCameraBob.hpp CPlayerCameraBob.cpp CPlayerCameraBob.hpp CPlayerCameraBob.cpp
CMorphBall.hpp CMorphBall.cpp CMorphBall.hpp CMorphBall.cpp
CMorphBallTrail.hpp CMorphBallTrail.cpp CMorphBallShadow.hpp CMorphBallShadow.cpp
CActor.hpp CActor.cpp CActor.hpp CActor.cpp
CAi.hpp CAi.cpp CAi.hpp CAi.cpp
CAiFuncMap.hpp CAiFuncMap.cpp CAiFuncMap.hpp CAiFuncMap.cpp

View File

@ -0,0 +1,143 @@
#include "CMorphBallShadow.hpp"
#include "CStateManager.hpp"
#include "World/CWorld.hpp"
#include "GameGlobalObjects.hpp"
#include "Graphics/CBooRenderer.hpp"
#include "World/CPlayer.hpp"
namespace urde
{
static union
{
struct
{
bool x_24_ : 1;
bool x_25_ : 1;
bool x_26_ : 1;
bool x_27_ : 1;
};
u16 _dummy = 0;
} s_flags;
void CMorphBallShadow::GatherAreas(CStateManager& mgr)
{
x18_areas.clear();
for (CGameArea* area = mgr.WorldNC()->GetChainHead(EChain::Alive);
area != CWorld::GetAliveAreasEnd();
area = area->GetNext())
{
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::NotOccluded;
if (area->IsPostConstructed())
occState = area->GetPostConstructed()->x10dc_occlusionState;
if (occState == CGameArea::EOcclusionState::Occluded)
x18_areas.push_back(area->GetAreaId());
}
}
void CMorphBallShadow::RenderIdBuffer(const zeus::CAABox& aabb, CStateManager& mgr, CPlayer& player)
{
xb8_ = aabb;
x0_actors.clear();
x18_areas.clear();
x30_worldModelBits.clear();
s_flags.x_26_ = true;
if (!s_flags.x_27_)
{
xd0_hasIds = false;
return;
}
GatherAreas(mgr);
g_Renderer->BindBallShadowIdTarget();
CGraphics::g_BooMainCommandQueue->clearTarget();
zeus::CTransform backupViewMtx = CGraphics::g_ViewMatrix;
CGraphics::CProjectionState backupProjection = CGraphics::g_Proj;
zeus::CVector2f backupDepth = CGraphics::g_CachedDepthRange;
zeus::CTransform viewMtx(zeus::CVector3f::skRight, zeus::CVector3f::skDown, zeus::CVector3f::skForward,
zeus::CVector3f((aabb.min.x + aabb.max.x) * 0.5f,
(aabb.min.y + aabb.max.y) * 0.5f,
aabb.max.z));
CGraphics::SetDepthRange(0.f, 1.f);
float vpX = (aabb.max.x - aabb.min.x) * 0.5f;
float vpY = (aabb.max.y - aabb.min.y) * 0.5f;
float vpZ = (aabb.max.z - aabb.min.z) + FLT_EPSILON;
CGraphics::SetOrtho(-vpX, vpX, vpY, -vpY, 0.f, vpZ);
rstl::reserved_vector<TUniqueId, 1024> nearItems;
mgr.BuildNearList(nearItems, aabb, CMaterialFilter::skPassEverything, &player);
CGraphics::SetViewPointMatrix(viewMtx);
int alphaVal = 4;
for (TUniqueId id : nearItems)
{
if (alphaVal > 255)
break;
const CActor* actor = static_cast<const CActor*>(mgr.GetObjectById(id));
if (!actor || !actor->CanDrawStatic())
continue;
x0_actors.push_back(actor);
const CModelData* modelData = actor->GetModelData();
zeus::CTransform modelXf = actor->GetTransform() * zeus::CTransform::Scale(modelData->GetScale());
CGraphics::SetModelMatrix(modelXf);
CModelFlags flags(0, 0, 3, zeus::CColor{1.f, 1.f, 1.f, alphaVal / 255.f});
flags.m_extendedShaderIdx = 5; // Do solid color draw
const CBooModel& model = *modelData->PickStaticModel(CModelData::EWhichModel::Normal);
const_cast<CBooModel&>(model).VerifyCurrentShader(flags.m_matSetIdx);
model.DrawNormal(flags, nullptr, nullptr);
alphaVal += 4;
}
CGraphics::SetModelMatrix(zeus::CTransform::Identity());
g_Renderer->FindOverlappingWorldModels(x30_worldModelBits, aabb);
alphaVal = g_Renderer->DrawOverlappingWorldModelIDs(alphaVal, x30_worldModelBits, aabb);
g_Renderer->ResolveBallShadowIdTarget();
g_Renderer->BindMainDrawTarget();
CGraphics::SetViewPointMatrix(backupViewMtx);
CGraphics::SetProjectionState(backupProjection);
CGraphics::SetDepthRange(backupDepth[0], backupDepth[1]);
xd0_hasIds = alphaVal != 4;
}
bool CMorphBallShadow::AreasValid(CStateManager& mgr) const
{
auto it = x18_areas.begin();
for (CGameArea* area = mgr.WorldNC()->GetChainHead(EChain::Alive);
area != CWorld::GetAliveAreasEnd();
area = area->GetNext())
{
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::NotOccluded;
if (area->IsPostConstructed())
occState = area->GetPostConstructed()->x10dc_occlusionState;
if (occState != CGameArea::EOcclusionState::Occluded)
continue;
if (it == x18_areas.end())
return false;
if (*it != area->GetAreaId())
return false;
++it;
}
return true;
}
void CMorphBallShadow::Render(CStateManager& mgr, float alpha)
{
if (!xd0_hasIds || !AreasValid(mgr))
return;
}
}

View File

@ -0,0 +1,35 @@
#ifndef __URDE_CMORPHBALLSHADOW_HPP__
#define __URDE_CMORPHBALLSHADOW_HPP__
#include "CToken.hpp"
#include "Graphics/CTexture.hpp"
#include "zeus/CAABox.hpp"
namespace urde
{
class CStateManager;
class CPlayer;
class CGameArea;
class CActor;
class CMorphBallShadow
{
std::list<const CActor*> x0_actors;
std::list<TAreaId> x18_areas;
std::vector<u32> x30_worldModelBits;
//CTexture x40_;
//TToken<CTexture> xa8_ballFade;
//int xb0_idW;
//int xb4_idH;
zeus::CAABox xb8_;
bool xd0_hasIds = false;
void GatherAreas(CStateManager& mgr);
bool AreasValid(CStateManager& mgr) const;
public:
void RenderIdBuffer(const zeus::CAABox& aabb, CStateManager& mgr, CPlayer& player);
void Render(CStateManager& mgr, float alpha);
};
}
#endif // __URDE_CMORPHBALLSHADOW_HPP__

View File

@ -1,69 +0,0 @@
#include "CMorphBallTrail.hpp"
#include "CStateManager.hpp"
#include "World/CWorld.hpp"
namespace urde
{
static union
{
struct
{
bool x_24_ : 1;
bool x_25_ : 1;
bool x_26_ : 1;
bool x_27_ : 1;
};
u16 _dummy = 0;
} s_flags;
CMorphBallTrail::CMorphBallTrail(int w, int h, const TToken<CTexture>& fadeTex)
: xb0_w(w), xb4_h(h), xa8_ballFade(fadeTex)
{
m_gfxToken = CGraphics::CommitResources([this, w, h](boo::IGraphicsDataFactory::Context& ctx)
{
m_renderTex = ctx.newRenderTexture(w, h, true, false);
return true;
});
}
void CMorphBallTrail::GatherAreas(CStateManager& mgr)
{
x18_areas.clear();
for (CGameArea* area = mgr.WorldNC()->GetChainHead(EChain::Alive);
area != CWorld::GetAliveAreasEnd();
area = area->GetNext())
{
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::NotOccluded;
if (area->IsPostConstructed())
occState = area->GetPostConstructed()->x10dc_occlusionState;
if (occState == CGameArea::EOcclusionState::Occluded)
x18_areas.push_back(area);
}
}
void CMorphBallTrail::RenderToTex(const zeus::CAABox& aabb, CStateManager& mgr, CPlayer& player)
{
xb8_ = aabb;
x0_.clear();
x18_areas.clear();
x30_.clear();
s_flags.x_26_ = true;
if (!s_flags.x_27_)
{
xd0_ = false;
return;
}
GatherAreas(mgr);
// TODO: finish
}
void CMorphBallTrail::Render(CStateManager& mgr)
{
}
}

View File

@ -1,36 +0,0 @@
#ifndef __URDE_CMORPHBALLTRAIL_HPP__
#define __URDE_CMORPHBALLTRAIL_HPP__
#include "CToken.hpp"
#include "Graphics/CTexture.hpp"
#include "zeus/CAABox.hpp"
namespace urde
{
class CStateManager;
class CPlayer;
class CGameArea;
class CMorphBallTrail
{
std::list<u32> x0_;
std::list<CGameArea*> x18_areas;
std::vector<u32> x30_;
//CTexture x40_;
boo::GraphicsDataToken m_gfxToken;
boo::ITextureR* m_renderTex;
TToken<CTexture> xa8_ballFade;
int xb0_w;
int xb4_h;
zeus::CAABox xb8_;
bool xd0_ = false;
void GatherAreas(CStateManager& mgr);
public:
CMorphBallTrail(int w, int h, const TToken<CTexture>& fadeTex);
void RenderToTex(const zeus::CAABox& aabb, CStateManager& mgr, CPlayer& player);
void Render(CStateManager& mgr);
};
}
#endif // __URDE_CMORPHBALLTRAIL_HPP__

2
hecl

@ -1 +1 @@
Subproject commit c9948da598998fe630883639e63b4059adcd9cb3 Subproject commit b80547d01fb70f349eb6128bd9c44921763f2821

@ -1 +1 @@
Subproject commit ccceebc331453fd3f71440ab8f14511572e36918 Subproject commit 717a6bbb1dd3a9dbe9ab85e58033c8ebca163a92

View File

@ -3,7 +3,7 @@
#include "VISIRenderer.hpp" #include "VISIRenderer.hpp"
#include "zeus/CAABox.hpp" #include "zeus/CAABox.hpp"
#include "hecl/extern/xxhash/xxhash.h" #include "hecl/extern/boo/xxhash/xxhash.h"
#include "athena/MemoryWriter.hpp" #include "athena/MemoryWriter.hpp"
#include "hecl/hecl.hpp" #include "hecl/hecl.hpp"
#include <unordered_map> #include <unordered_map>