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

@ -603,6 +603,25 @@ zeus::CFrustum CStateManager::SetupViewForDraw(const SViewport& vp) const {
return frustum;
}
zeus::CFrustum CStateManager::SetupViewForCubeFaceDraw(const zeus::CVector3f& pos, int face) const {
zeus::CTransform mainCamXf = x870_cameraManager->GetCurrentCameraTransform(*this);
zeus::CTransform camXf = zeus::CTransform(mainCamXf.basis * CGraphics::skCubeBasisMats[face], pos);
g_Renderer->SetWorldViewpoint(camXf);
CBooModel::SetNewPlayerPositionAndTime(x84c_player->GetTranslation());
constexpr float width = CUBEMAP_RES;
g_Renderer->SetViewport(0, 0, width, width);
CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR);
constexpr float fov = zeus::degToRad(90.f);
g_Renderer->SetPerspective(zeus::radToDeg(fov), width, width, 0.2f, 750.f);
zeus::CFrustum frustum;
zeus::CProjection proj;
proj.setPersp(zeus::SProjPersp{fov, 1.f, 0.2f, 750.f});
frustum.updatePlanes(camXf, proj);
g_Renderer->SetClippingPlanes(frustum);
CGraphics::SetModelMatrix(zeus::CTransform());
return frustum;
}
void CStateManager::ResetViewAfterDraw(const SViewport& backupViewport,
const zeus::CTransform& backupViewMatrix) const {
g_Renderer->SetViewport(backupViewport.x0_left, backupViewport.x4_top, backupViewport.x8_width,
@ -621,14 +640,17 @@ void CStateManager::ResetViewAfterDraw(const SViewport& backupViewport,
void CStateManager::DrawWorld() const {
CTimeProvider timeProvider(xf14_curTimeMod900);
SViewport backupViewport = g_Viewport;
zeus::CFrustum frustum = SetupViewForDraw(g_Viewport);
zeus::CTransform backupViewMatrix = CGraphics::g_ViewMatrix;
/* Area camera is in (not necessarily player) */
TAreaId visAreaId = GetVisAreaId();
x850_world->TouchSky();
DrawWorldCubeFaces();
zeus::CFrustum frustum = SetupViewForDraw(g_Viewport);
zeus::CTransform backupViewMatrix = CGraphics::g_ViewMatrix;
int areaCount = 0;
const CGameArea* areaArr[10];
for (const CGameArea& area : *x850_world) {
@ -851,6 +873,107 @@ void CStateManager::DrawWorld() const {
DrawAdditionalFilters();
}
void CStateManager::DrawActorCubeFaces(CActor& actor, int& cubeInst) const {
if (!actor.m_reflectionCube ||
(!TCastToPtr<CPlayer>(actor) && (!actor.GetActive() || !actor.IsDrawEnabled() || actor.xe4_30_outOfFrustum)))
return;
TAreaId visAreaId = actor.GetAreaIdAlways();
SViewport backupVp = g_Viewport;
int areaCount = 0;
const CGameArea* areaArr[10];
for (const CGameArea& area : *x850_world) {
if (areaCount == 10)
break;
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded;
if (area.IsPostConstructed())
occState = area.GetOcclusionState();
if (occState == CGameArea::EOcclusionState::Visible)
areaArr[areaCount++] = &area;
}
for (int f = 0; f < 6; ++f) {
CGraphics::g_BooMainCommandQueue->setRenderTarget(actor.m_reflectionCube, f);
SetupViewForCubeFaceDraw(actor.GetRenderBounds().center(), f);
CGraphics::g_BooMainCommandQueue->clearTarget();
std::sort(std::begin(areaArr), std::begin(areaArr) + areaCount,
[visAreaId](const CGameArea* a, const CGameArea* b) {
if (a->x4_selfIdx == b->x4_selfIdx)
return false;
if (visAreaId == a->x4_selfIdx)
return false;
if (visAreaId == b->x4_selfIdx)
return true;
return CGraphics::g_ViewPoint.dot(a->GetAABB().center()) >
CGraphics::g_ViewPoint.dot(b->GetAABB().center());
});
int pvsCount = 0;
CPVSVisSet pvsArr[10];
for (const CGameArea** area = areaArr; area != areaArr + areaCount; ++area) {
const CGameArea* areaPtr = *area;
CPVSVisSet& pvsSet = pvsArr[pvsCount++];
pvsSet.Reset(EPVSVisSetState::OutOfBounds);
GetVisSetForArea(areaPtr->x4_selfIdx, visAreaId, pvsSet);
}
for (int i = areaCount - 1; i >= 0; --i) {
const CGameArea& area = *areaArr[i];
SetupFogForArea(area);
g_Renderer->EnablePVS(pvsArr[i], area.x4_selfIdx);
g_Renderer->SetWorldLightFadeLevel(area.GetPostConstructed()->x1128_worldLightingLevel);
g_Renderer->UpdateAreaUniforms(area.x4_selfIdx, false, true, cubeInst * 6 + f);
g_Renderer->DrawUnsortedGeometry(area.x4_selfIdx, 0x2, 0x0);
}
if (!SetupFogForDraw())
g_Renderer->SetWorldFog(ERglFogMode::None, 0.f, 1.f, zeus::skBlack);
x850_world->DrawSky(zeus::CTransform::Translate(CGraphics::g_ViewPoint));
for (int i = 0; i < areaCount; ++i) {
const CGameArea& area = *areaArr[i];
CPVSVisSet& pvs = pvsArr[i];
SetupFogForArea(area);
g_Renderer->SetWorldLightFadeLevel(area.GetPostConstructed()->x1128_worldLightingLevel);
g_Renderer->EnablePVS(pvs, area.x4_selfIdx);
g_Renderer->DrawSortedGeometry(area.x4_selfIdx, 0x2, 0x0);
}
}
CGraphics::g_BooMainCommandQueue->generateMipmaps(actor.m_reflectionCube);
CBooRenderer::BindMainDrawTarget();
g_Renderer->SetViewport(backupVp.x0_left, backupVp.x4_top, backupVp.x8_width, backupVp.xc_height);
++cubeInst;
}
void CStateManager::DrawWorldCubeFaces() const {
int areaCount = 0;
const CGameArea* areaArr[10];
for (const CGameArea& area : *x850_world) {
if (areaCount == 10)
break;
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded;
if (area.IsPostConstructed())
occState = area.GetOcclusionState();
if (occState == CGameArea::EOcclusionState::Visible)
areaArr[areaCount++] = &area;
}
for (int ai = 0; ai < areaCount; ++ai) {
const CGameArea& area = *areaArr[ai];
int cubeInst = 0;
for (CEntity* ent : *area.GetAreaObjects()) {
if (TCastToPtr<CActor> actor = ent)
DrawActorCubeFaces(*actor, cubeInst);
}
}
}
void CStateManager::SetupFogForArea(TAreaId area) const {
if (area == kInvalidAreaId)
area = x8cc_nextAreaId;

View File

@ -245,8 +245,11 @@ public:
void DrawAdditionalFilters() const;
zeus::CFrustum SetupDrawFrustum(const SViewport& vp) const;
zeus::CFrustum SetupViewForDraw(const SViewport& vp) const;
zeus::CFrustum SetupViewForCubeFaceDraw(const zeus::CVector3f& pos, int face) const;
void ResetViewAfterDraw(const SViewport& backupViewport, const zeus::CTransform& backupViewMatrix) const;
void DrawWorld() const;
void DrawActorCubeFaces(CActor& actor, int& cubeInst) const;
void DrawWorldCubeFaces() const;
void SetupFogForArea(TAreaId area) const;
void SetupFogForAreaNonCurrent(TAreaId area) const;
void SetupFogForArea(const CGameArea& area) const;

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

View File

@ -864,9 +864,9 @@ void CMain::Shutdown() {
CFluidPlaneShader::Shutdown();
CFluidPlaneManager::RippleMapTex.reset();
CNESShader::Shutdown();
CBooModel::Shutdown();
CGraphics::ShutdownBoo();
ShutdownDiscord();
CBooModel::AssertAllFreed();
}
boo::IWindow* CMain::GetMainWindow() const { return m_mainWindow; }

View File

@ -2085,7 +2085,7 @@ void CPlayerGun::Render(const CStateManager& mgr, const zeus::CVector3f& pos, co
CGraphics::CProjectionState projState = CGraphics::GetProjectionState();
CModelFlags useFlags = flags;
if (x0_lights.HasShadowLight())
useFlags.m_extendedShader = EExtendedShader::WorldShadow;
useFlags.m_extendedShader = EExtendedShader::LightingCubeReflectionWorldShadow;
CModelFlags beamFlags = useFlags;
if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal)
beamFlags = kThermalFlags[int(x310_currentBeam)];

View File

@ -431,6 +431,13 @@ void CActor::_CreateShadow() {
x94_simpleShadow.reset(new CSimpleShadow(1.f, 1.f, 20.f, 0.05f));
}
void CActor::_CreateReflectionCube() {
CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) {
m_reflectionCube = ctx.newCubeRenderTexture(CUBEMAP_RES, CUBEMAP_MIPS);
return true;
} BooTrace);
}
void CActor::SetCallTouch(bool callTouch) { xe5_28_callTouch = callTouch; }
bool CActor::GetCallTouch() const { return xe5_28_callTouch; }

View File

@ -76,7 +76,11 @@ protected:
};
u32 dummy = 0;
};
boo::ObjToken<boo::ITextureCubeR> m_reflectionCube;
void _CreateShadow();
void _CreateReflectionCube();
void UpdateSfxEmitters();
void DrawTouchBounds() const;
void RenderInternal(const CStateManager& mgr) const;

View File

@ -1035,10 +1035,8 @@ void CGameArea::FillInStaticGeometry(bool textures) {
}
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
/* Shared geometry uniform buffer - one for normal render, one for shadow render */
for (int i = 0; i < 2; ++i)
matSet.m_geomLayout->m_sharedBuffer[i] =
ctx.newDynamicBuffer(boo::BufferUse::Uniform, matSet.m_geomLayout->m_geomBufferSize, 1);
/* Reserve extra buffers for 16 cubemaps and shadow rendering */
matSet.m_geomLayout->ReserveSharedBuffers(ctx, 98);
/* Models */
for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts) {

View File

@ -1418,6 +1418,7 @@ void CMorphBall::Render(const CStateManager& mgr, const CActorLights* lights) co
if (dying) {
zeus::CColor modColor(0.f, zeus::clamp(0.f, 1.f - x0_player.x9f4_deathTime / 0.2f * 6.f, 1.f));
CModelFlags flags(7, u8(x5c_ballModelShader), 1, modColor);
flags.m_extendedShader = EExtendedShader::LightingCubeReflection;
x58_ballModel->Render(mgr, ballToWorld, nullptr, flags);
}
@ -1426,13 +1427,15 @@ void CMorphBall::Render(const CStateManager& mgr, const CActorLights* lights) co
if (x1e44_damageEffect > 0.f)
flags = CModelFlags(1, 0, 3, zeus::CColor(1.f, 1.f - x1e44_damageEffect, 1.f - x1e44_damageEffect, 1.f));
flags.m_extendedShader = EExtendedShader::LightingCubeReflection;
if (x1c1c_rainSplashGen && x1c1c_rainSplashGen->IsRaining())
CSkinnedModel::SetPointGeneratorFunc(x1c1c_rainSplashGen.get(), PointGenerator);
if (x1c34_boostLightFactor != 1.f) {
if (lights->HasShadowLight()) {
x1c14_worldShadow->EnableModelProjectedShadow(ballToWorld, lights->GetShadowLightArrIndex(), 1.f);
flags.m_extendedShader = EExtendedShader::WorldShadow;
flags.m_extendedShader = EExtendedShader::LightingCubeReflectionWorldShadow;
}
x58_ballModel->Render(mgr, ballToWorld, lights, flags);
x1c14_worldShadow->DisableModelProjectedShadow();
@ -1493,10 +1496,11 @@ void CMorphBall::Render(const CStateManager& mgr, const CActorLights* lights) co
if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::SpiderBall) && x60_spiderBallGlassModel) {
float tmp = std::max(x1c38_spiderLightFactor, x1c34_boostLightFactor);
CModelFlags sflags(0, u8(x64_spiderBallGlassModelShader), 3, zeus::skWhite);
sflags.m_extendedShader = EExtendedShader::LightingCubeReflection;
if (tmp != 1.f) {
if (lights->HasShadowLight()) {
x1c14_worldShadow->EnableModelProjectedShadow(ballToWorld, lights->GetShadowLightArrIndex(), 1.f);
sflags.m_extendedShader = EExtendedShader::WorldShadow;
sflags.m_extendedShader = EExtendedShader::LightingCubeReflectionWorldShadow;
}
x60_spiderBallGlassModel->Render(mgr, ballToWorld, x1c18_actorLights.get(), sflags);
x1c14_worldShadow->DisableModelProjectedShadow();

View File

@ -118,6 +118,8 @@ CPlayer::CPlayer(TUniqueId uid, const zeus::CTransform& xf, const zeus::CAABox&
x64_modelData->SetScale(playerScale);
x7f0_ballTransitionBeamModel->SetScale(playerScale);
LoadAnimationTokens();
_CreateReflectionCube();
}
void CPlayer::InitializeBallTransition() {
@ -1141,7 +1143,9 @@ void CPlayer::RenderGun(const CStateManager& mgr, const zeus::CVector3f& pos) co
if ((mgr.GetCameraManager()->IsInFirstPersonCamera() && x2f4_cameraState == EPlayerCameraState::FirstPerson) ||
(x2f8_morphBallState == EPlayerMorphBallState::Morphing &&
x498_gunHolsterState == EGunHolsterState::Holstering)) {
CBooModel::SetReflectionCube(m_reflectionCube);
CModelFlags flags(5, 0, 3, zeus::CColor(1.f, x494_gunAlpha));
flags.m_extendedShader = EExtendedShader::LightingCubeReflection;
x490_gun->Render(mgr, pos, flags);
}
}
@ -1152,6 +1156,7 @@ void CPlayer::Render(const CStateManager& mgr) const {
if (TCastToConstPtr<CCinematicCamera> cam = mgr.GetCameraManager()->GetCurrentCamera(mgr))
doRender = (x2f8_morphBallState == EPlayerMorphBallState::Morphed && cam->GetFlags() & 0x40);
if (x2f4_cameraState != EPlayerCameraState::FirstPerson && doRender) {
CBooModel::SetReflectionCube(m_reflectionCube);
bool doTransitionRender = false;
bool doBallRender = false;
switch (x2f8_morphBallState) {
@ -1161,6 +1166,7 @@ void CPlayer::Render(const CStateManager& mgr) const {
if (HasTransitionBeamModel()) {
x7f0_ballTransitionBeamModel->Touch(mgr, 0);
CModelFlags flags(0, 0, 3, zeus::skWhite);
flags.m_extendedShader = EExtendedShader::LightingCubeReflection;
x7f0_ballTransitionBeamModel->Render(mgr, x7f4_gunWorldXf, x90_actorLights.get(), flags);
}
break;
@ -1184,6 +1190,7 @@ void CPlayer::Render(const CStateManager& mgr) const {
CPhysicsActor::Render(mgr);
if (HasTransitionBeamModel()) {
CModelFlags flags(5, 0, 3, zeus::CColor(1.f, x588_alpha));
flags.m_extendedShader = EExtendedShader::LightingCubeReflection;
x7f0_ballTransitionBeamModel->Render(CModelData::EWhichModel::Normal, x7f4_gunWorldXf, x90_actorLights.get(),
flags);
}
@ -1206,10 +1213,12 @@ void CPlayer::Render(const CStateManager& mgr) const {
if (alpha != 0.f) {
CModelData& data = *x730_transitionModels[i];
CModelFlags flags(5, 0, 3, zeus::CColor(1.f, alpha));
flags.m_extendedShader = EExtendedShader::LightingCubeReflection;
data.Render(CModelData::GetRenderingModel(mgr), *x658_transitionModelXfs.GetEntry(ni), x90_actorLights.get(),
flags);
if (HasTransitionBeamModel()) {
CModelFlags flags(5, 0, 3, zeus::CColor(1.f, alpha));
flags.m_extendedShader = EExtendedShader::LightingCubeReflection;
x7f0_ballTransitionBeamModel->Render(CModelData::EWhichModel::Normal, *x594_transisionBeamXfs.GetEntry(ni),
x90_actorLights.get(), flags);
}
@ -1229,6 +1238,7 @@ void CPlayer::Render(const CStateManager& mgr) const {
if (morphFactor > ballAlphaStart) {
CModelFlags flags(5, u8(x768_morphball->GetMorphballModelShader()), 3,
zeus::CColor(1.f, ballAlphaMag * (morphFactor - ballAlphaStart)));
flags.m_extendedShader = EExtendedShader::LightingCubeReflection;
x768_morphball->GetMorphballModelData().Render(mgr, x768_morphball->GetBallToWorld(), x90_actorLights.get(),
flags);
}
@ -1252,6 +1262,7 @@ void CPlayer::Render(const CStateManager& mgr) const {
ballAlpha *= 0.5f;
if (ballAlpha > 0.f) {
CModelFlags flags(7, 0, 3, zeus::CColor(1.f, ballAlpha));
flags.m_extendedShader = EExtendedShader::LightingCubeReflection;
x768_morphball->GetMorphballModelData().Render(
mgr,
x768_morphball->GetBallToWorld() * zeus::CTransform::RotateZ(theta) * zeus::CTransform::Scale(scale),

View File

@ -35,6 +35,8 @@ CScriptPlayerActor::CScriptPlayerActor(TUniqueId uid, std::string_view name, con
SetActorLights(aParams.GetLightParameters().MakeActorLights());
xe7_29_drawEnabled = true;
x2e3_24_isPlayerActor = true;
_CreateReflectionCube();
}
u32 CScriptPlayerActor::GetSuitCharIdx(const CStateManager& mgr, CPlayerState::EPlayerSuit suit) const {
@ -360,6 +362,7 @@ void CScriptPlayerActor::PreRender(CStateManager& mgr, const zeus::CFrustum& fru
}
if (x2e8_suitRes.GetCharacterNodeId() == 3)
g_Renderer->AllocatePhazonSuitMaskTexture();
xb4_drawFlags.m_extendedShader = EExtendedShader::LightingCubeReflection;
CScriptActor::PreRender(mgr, frustum);
}
@ -370,6 +373,8 @@ void CScriptPlayerActor::AddToRenderer(const zeus::CFrustum& frustum, const CSta
}
void CScriptPlayerActor::Render(const CStateManager& mgr) const {
CBooModel::SetReflectionCube(m_reflectionCube);
bool phazonSuit = x2e8_suitRes.GetCharacterNodeId() == 3;
if (phazonSuit) {
// Draw into alpha buffer
@ -387,7 +392,7 @@ void CScriptPlayerActor::Render(const CStateManager& mgr) const {
CModelFlags flags(5, 0, 3, zeus::skWhite);
flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly;
x314_beamModelData->Render(mgr, modelXf, x90_actorLights.get(), flags);
flags.m_extendedShader = EExtendedShader::Lighting;
flags.m_extendedShader = EExtendedShader::LightingCubeReflection;
flags.x4_color = zeus::CColor{1.f, xb4_drawFlags.x4_color.a()};
x314_beamModelData->Render(mgr, modelXf, x90_actorLights.get(), flags);
}

View File

@ -167,64 +167,107 @@ void CWorldTransManager::Update(float dt) {
}
}
void CWorldTransManager::DrawAllModels() {
CActorLights lights(0, zeus::skZero3f, 4, 4, 0, 0, 0, 0.1f);
lights.BuildFakeLightList(x4_modelData->x1a0_lights, zeus::CColor{0.1f, 0.1f, 0.1f, 1.0f});
void CWorldTransManager::DrawPlatformModels(CActorLights* lights) {
CModelFlags flags = {};
flags.m_extendedShader = EExtendedShader::Lighting;
if (!x4_modelData->x100_bgModelData[0].IsNull()) {
zeus::CTransform xf0 = zeus::CTransform::Translate(0.f, 0.f, -(2.f * x1c_bgHeight - x18_bgOffset));
x4_modelData->x100_bgModelData[0].Render(CModelData::EWhichModel::Normal, xf0, &lights, flags);
x4_modelData->x100_bgModelData[0].Render(CModelData::EWhichModel::Normal, xf0, lights, flags);
}
if (!x4_modelData->x100_bgModelData[1].IsNull()) {
zeus::CTransform xf1 = zeus::CTransform::Translate(0.f, 0.f, x18_bgOffset - x1c_bgHeight);
x4_modelData->x100_bgModelData[1].Render(CModelData::EWhichModel::Normal, xf1, &lights, flags);
x4_modelData->x100_bgModelData[1].Render(CModelData::EWhichModel::Normal, xf1, lights, flags);
}
if (!x4_modelData->x100_bgModelData[2].IsNull()) {
zeus::CTransform xf2 = zeus::CTransform::Translate(0.f, 0.f, x18_bgOffset);
x4_modelData->x100_bgModelData[2].Render(CModelData::EWhichModel::Normal, xf2, &lights, flags);
x4_modelData->x100_bgModelData[2].Render(CModelData::EWhichModel::Normal, xf2, lights, flags);
}
if (!x4_modelData->xb4_platformModelData.IsNull()) {
x4_modelData->xb4_platformModelData.Render(CModelData::EWhichModel::Normal, zeus::CTransform(), &lights,
x4_modelData->xb4_platformModelData.Render(CModelData::EWhichModel::Normal, zeus::CTransform(), lights,
flags);
}
}
void CWorldTransManager::DrawAllModels(CActorLights* lights) {
DrawPlatformModels(lights);
if (!x4_modelData->x1c_samusModelData.IsNull()) {
CModelFlags flags = {};
flags.m_extendedShader = EExtendedShader::LightingCubeReflection;
x4_modelData->x1c_samusModelData.AnimationData()->PreRender();
x4_modelData->x1c_samusModelData.Render(CModelData::EWhichModel::Normal, zeus::CTransform(), &lights,
x4_modelData->x1c_samusModelData.Render(CModelData::EWhichModel::Normal, zeus::CTransform(), lights,
flags);
if (!x4_modelData->x68_beamModelData.IsNull()) {
x4_modelData->x68_beamModelData.Render(CModelData::EWhichModel::Normal, x4_modelData->x170_gunXf, &lights, flags);
x4_modelData->x68_beamModelData.Render(CModelData::EWhichModel::Normal, x4_modelData->x170_gunXf, lights, flags);
}
}
}
void CWorldTransManager::DrawFirstPass() {
void CWorldTransManager::DrawFirstPass(CActorLights* lights) {
CBooModel::SetReflectionCube(m_reflectionCube[0]);
zeus::CTransform translateXf = zeus::CTransform::Translate(
x4_modelData->x1b4_shakeResult.x(), -3.5f * (1.f - zeus::clamp(0.f, x0_curTime / 10.f, 1.f)) - 3.5f,
x4_modelData->x1b4_shakeResult.y() + 2.f);
zeus::CTransform rotateXf =
zeus::CTransform::RotateZ(zeus::degToRad(zeus::clamp(0.f, x0_curTime / 25.f, 100.f) * 360.f + 180.f - 90.f));
CGraphics::SetViewPointMatrix(rotateXf * translateXf);
DrawAllModels();
DrawAllModels(lights);
m_camblur.draw(x4_modelData->x1c8_blurResult);
}
void CWorldTransManager::DrawSecondPass() {
void CWorldTransManager::DrawSecondPass(CActorLights* lights) {
CBooModel::SetReflectionCube(m_reflectionCube[1]);
const zeus::CVector3f& samusScale = x4_modelData->x0_samusRes.GetScale();
zeus::CTransform translateXf =
zeus::CTransform::Translate(-0.1f * samusScale.x(), -0.5f * samusScale.y(), 1.5f * samusScale.z());
zeus::CTransform rotateXf = zeus::CTransform::RotateZ(zeus::degToRad(
48.f * zeus::clamp(0.f, (x0_curTime - x4_modelData->x1d0_dissolveStartTime + 2.f) / 5.f, 1.f) + 180.f - 24.f));
CGraphics::SetViewPointMatrix(rotateXf * translateXf);
DrawAllModels();
DrawAllModels(lights);
}
void CWorldTransManager::DrawEnabled() {
CActorLights lights(0, zeus::skZero3f, 4, 4, 0, 0, 0, 0.1f);
lights.BuildFakeLightList(x4_modelData->x1a0_lights, zeus::CColor{0.1f, 0.1f, 0.1f, 1.0f});
SViewport backupVp = g_Viewport;
constexpr float width = CUBEMAP_RES;
CGraphics::g_BooMainCommandQueue->setRenderTarget(m_reflectionCube[0], 0);
g_Renderer->SetViewport(0, 0, width, width);
g_Renderer->SetPerspective(90.f, width, width, 0.2f, 750.f);
if (x0_curTime < x4_modelData->x1d4_dissolveEndTime) {
zeus::CTransform mainCamXf =
zeus::CTransform::RotateZ(zeus::degToRad(zeus::clamp(0.f, x0_curTime / 25.f, 100.f) * 360.f + 180.f - 90.f));
for (int face = 0; face < 6; ++face) {
CGraphics::g_BooMainCommandQueue->setRenderTarget(m_reflectionCube[0], face);
CGraphics::g_BooMainCommandQueue->clearTarget();
zeus::CTransform camXf = zeus::CTransform(mainCamXf.basis * CGraphics::skCubeBasisMats[face], zeus::CVector3f(0.f, 0.f, 1.5f));
g_Renderer->SetWorldViewpoint(camXf);
DrawPlatformModels(&lights);
}
CGraphics::g_BooMainCommandQueue->generateMipmaps(m_reflectionCube[0]);
}
if (x0_curTime > x4_modelData->x1d0_dissolveStartTime) {
zeus::CTransform mainCamXf = zeus::CTransform::RotateZ(zeus::degToRad(
48.f * zeus::clamp(0.f, (x0_curTime - x4_modelData->x1d0_dissolveStartTime + 2.f) / 5.f, 1.f) + 180.f - 24.f));
for (int face = 0; face < 6; ++face) {
CGraphics::g_BooMainCommandQueue->setRenderTarget(m_reflectionCube[1], face);
CGraphics::g_BooMainCommandQueue->clearTarget();
zeus::CTransform camXf = zeus::CTransform(mainCamXf.basis * CGraphics::skCubeBasisMats[face], zeus::CVector3f(0.f, 0.f, 1.5f));
g_Renderer->SetWorldViewpoint(camXf);
DrawPlatformModels(&lights);
}
CGraphics::g_BooMainCommandQueue->generateMipmaps(m_reflectionCube[1]);
}
CBooRenderer::BindMainDrawTarget();
g_Renderer->SetViewport(backupVp.x0_left, backupVp.x4_top, backupVp.x8_width, backupVp.xc_height);
float wsAspect = CWideScreenFilter::SetViewportToMatch(1.f);
g_Renderer->SetPerspective(CCameraManager::FirstPersonFOV(), wsAspect, CCameraManager::NearPlane(),
@ -232,16 +275,16 @@ void CWorldTransManager::DrawEnabled() {
g_Renderer->x318_26_requestRGBA6 = true;
if (x0_curTime <= x4_modelData->x1d0_dissolveStartTime)
DrawFirstPass();
DrawFirstPass(&lights);
else if (x0_curTime >= x4_modelData->x1d4_dissolveEndTime)
DrawSecondPass();
DrawSecondPass(&lights);
else {
float t = zeus::clamp(0.f, (x0_curTime - x4_modelData->x1d0_dissolveStartTime) / 2.f, 1.f);
DrawFirstPass();
DrawFirstPass(&lights);
SClipScreenRect rect(g_Viewport);
CGraphics::ResolveSpareTexture(rect);
CGraphics::g_BooMainCommandQueue->clearTarget(true, true);
DrawSecondPass();
DrawSecondPass(&lights);
m_dissolve.drawCropped(zeus::CColor{1.f, 1.f, 1.f, 1.f - t}, 1.f);
}
@ -335,6 +378,13 @@ void CWorldTransManager::EnableTransition(const CAnimRes& samusRes, CAssetId pla
x30_type = ETransType::Enabled;
x4_modelData.reset(new SModelDatas(samusRes));
if (!m_reflectionCube[0])
CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) {
m_reflectionCube[0] = ctx.newCubeRenderTexture(CUBEMAP_RES, CUBEMAP_MIPS);
m_reflectionCube[1] = ctx.newCubeRenderTexture(CUBEMAP_RES, CUBEMAP_MIPS);
return true;
} BooTrace);
x8_textData.reset();
x20_random.SetSeed(99);

View File

@ -77,10 +77,13 @@ private:
CWideScreenFilter m_widescreen = {EFilterType::Blend};
CCameraBlurFilter m_camblur;
boo::ObjToken<boo::ITextureCubeR> m_reflectionCube[2];
static int GetSuitCharIdx();
void DrawFirstPass();
void DrawSecondPass();
void DrawAllModels();
void DrawFirstPass(CActorLights* lights);
void DrawSecondPass(CActorLights* lights);
void DrawPlatformModels(CActorLights* lights);
void DrawAllModels(CActorLights* lights);
void UpdateLights(float dt);
void UpdateEnabled(float);
void UpdateDisabled(float);

View File

@ -14,7 +14,12 @@ TBINDING7 uniform sampler2D reflectionIndTex;
TBINDING8 uniform sampler2D extTex0;
TBINDING9 uniform sampler2D extTex1;
TBINDING10 uniform sampler2D extTex2;
#if defined(URDE_LIGHTING_CUBE_REFLECTION) || defined(URDE_LIGHTING_CUBE_REFLECTION_SHADOW)
TBINDING11 uniform samplerCube reflectionTex;
#else
TBINDING11 uniform sampler2D reflectionTex;
#endif
const vec3 kRGBToYPrime = vec3(0.257, 0.504, 0.098);
@ -84,7 +89,7 @@ vec3 SampleTexture_alpha() { return texture(alpha, vtf.alphaUv).rgb; }
float SampleTextureAlpha_alpha() { return dot(texture(alpha, vtf.alphaUv).rgb, kRGBToYPrime); }
#endif
#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW) || defined(URDE_DISINTEGRATE)
#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW) || defined(URDE_LIGHTING_CUBE_REFLECTION) || defined(URDE_LIGHTING_CUBE_REFLECTION_SHADOW) || defined(URDE_DISINTEGRATE)
struct Fog {
vec4 color;
float A;
@ -94,7 +99,7 @@ struct Fog {
};
#endif
#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW)
#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW) || defined(URDE_LIGHTING_CUBE_REFLECTION) || defined(URDE_LIGHTING_CUBE_REFLECTION_SHADOW)
struct Light {
vec4 pos;
vec4 dir;
@ -119,7 +124,7 @@ const vec4 colorReg1 = vec4(1.0);
const vec4 colorReg2 = vec4(1.0);
#endif
#if defined(URDE_LIGHTING)
#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_CUBE_REFLECTION)
vec3 LightingFunc() {
vec4 ret = ambient;
@ -176,7 +181,7 @@ UBINDING2 uniform MBShadowUniform {
};
#endif
#if defined(URDE_LIGHTING_SHADOW)
#if defined(URDE_LIGHTING_SHADOW) || defined(URDE_LIGHTING_CUBE_REFLECTION_SHADOW)
vec3 LightingFunc() {
vec2 shadowUV = vtf.extUvs[0];
shadowUV.y = 1.0 - shadowUV.y;
@ -224,7 +229,7 @@ vec3 LightingFunc() {
}
#endif
#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW) || defined(URDE_DISINTEGRATE)
#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW) || defined(URDE_LIGHTING_CUBE_REFLECTION) || defined(URDE_LIGHTING_CUBE_REFLECTION_SHADOW) || defined(URDE_DISINTEGRATE)
vec4 FogFunc(vec4 colorIn) {
float fogZ;
float fogF = clamp((fog.A / (fog.B - gl_FragCoord.z)) - fog.C, 0.0, 1.0);
@ -257,7 +262,7 @@ vec4 FogFunc(vec4 colorIn) {
}
#endif
#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW)
#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW) || defined(URDE_LIGHTING_CUBE_REFLECTION) || defined(URDE_LIGHTING_CUBE_REFLECTION_SHADOW)
vec4 PostFunc(vec4 colorIn) {
return FogFunc(colorIn) * mulColor + addColor;
}
@ -303,7 +308,10 @@ vec4 PostFunc(vec4 colorIn) {
}
#endif
#if defined(URDE_REFLECTION_SIMPLE)
#if defined(URDE_LIGHTING_CUBE_REFLECTION) || defined(URDE_LIGHTING_CUBE_REFLECTION_SHADOW)
vec3 ReflectionFunc(float roughness) { return texture(reflectionTex, reflect(vtf.mvPos.xyz, vtf.mvNorm.xyz),
roughness * 5.0).rgb; }
#elif defined(URDE_REFLECTION_SIMPLE)
vec3 ReflectionFunc() { return texture(reflectionTex, vtf.dynReflectionUvs[1]).rgb * vtf.dynReflectionAlpha; }
#elif defined(URDE_REFLECTION_INDIRECT)
vec3 ReflectionFunc() { return texture(reflectionTex, (texture(reflectionIndTex, vtf.dynReflectionUvs[0]).ab -
@ -316,7 +324,12 @@ layout(location=0) out vec4 colorOut;
void main() {
vec3 lighting = LightingFunc();
vec4 tmp;
#if defined(URDE_DIFFUSE_ONLY)
#if defined(URDE_LIGHTING_CUBE_REFLECTION) || defined(URDE_LIGHTING_CUBE_REFLECTION_SHADOW)
tmp.rgb = (SampleTexture_lightmap() * colorReg1.rgb + lighting) * SampleTexture_diffuse() +
SampleTexture_emissive() + (SampleTexture_specular() + SampleTexture_extendedSpecular() * lighting) *
(SampleTexture_reflection() * ReflectionFunc(clamp(0.5 - SampleTextureAlpha_specular(), 0.0, 1.0)) * 2.0);
tmp.a = SampleTextureAlpha_alpha();
#elif defined(URDE_DIFFUSE_ONLY)
tmp.rgb = SampleTexture_diffuse();
tmp.a = SampleTextureAlpha_alpha();
#elif defined(RETRO_SHADER)

View File

@ -96,6 +96,7 @@ static std::string _BuildVS(const SModelShadersInfo& info) {
if (info.m_tag.getWeightCount())
vertOut << "layout(location="sv << 2 + info.m_tag.getColorCount() + info.m_tag.getUvCount() <<
") in vec4 weightIn["sv << unsigned(info.m_tag.getWeightCount()) << "];"sv;
vertOut << '\n';
vertOut << "#define URDE_TCG_EXPR "sv;
using UVAnimType = BlendMaterial::UVAnimType;

2
hecl

@ -1 +1 @@
Subproject commit 4c65ccf85be21b9869dcdaea09692ca6677f3204
Subproject commit 9bb5181bbd9657c6b48d9a214352a72b26d411a0