Files
HL2Overcharged/game/client/overcharged/c_lights.cpp
2025-05-21 21:09:22 +03:00

422 lines
12 KiB
C++

#include "cbase.h"
#include "c_lights.h"
#include "game_controls/FloatSlider.h"
#include "vgui_controls/TextEntry.h"
#include "vgui_controls/Frame.h"
#include "vgui/IInput.h"
#include "ienginevgui.h"
#include "tier0/memdbgon.h"
C_EnvLight *g_pCSMEnvLight = NULL;
//static ConVar r_csm_enabled( "r_csm_enabled", "0", FCVAR_HIDDEN, "0 = off, 1 = on, 2 = force" );
ConVar r_post_draw_rtt_enabled("r_post_draw_rtt_enabled", "1", 0, "0 = off, 1 = on");
//static ConVar r_post_draw_csm_quality_mode("r_post_draw_csm_quality_mode", "3", FCVAR_ARCHIVE | FCVAR_ARCHIVE);
CON_COMMAND(csm_change_quality, "")
{
if (g_pCSMEnvLight)
g_pCSMEnvLight->ChangeCSMQuality();
}
void ChangeCSMQuality(ConVar *pConVar, char *pszString)
{
if (g_pCSMEnvLight)
g_pCSMEnvLight->ChangeCSMQuality();
}
static ConVar r_post_draw_csm_quality_mode("r_post_draw_csm_quality_mode", "3", FCVAR_ARCHIVE, "", ((FnChangeCallback_t)ChangeCSMQuality));
IMPLEMENT_CLIENTCLASS_DT_NOBASE(C_EnvLight, DT_CEnvLight, CEnvLight)
RecvPropQAngles(RECVINFO(m_angSunAngles)),
RecvPropVector(RECVINFO(m_vecLight)),
RecvPropVector(RECVINFO(m_vecAmbient)),
RecvPropBool(RECVINFO(m_bCascadedShadowMappingEnabled)),
RecvPropBool(RECVINFO(csmEnableLightColor)),
RecvPropBool(RECVINFO(csmEnableAmbientLightColor)),
RecvPropInt(RECVINFO(csmLightColor)),
RecvPropInt(RECVINFO(csmAmbientColor)),
RecvPropInt(RECVINFO(cmsFov)),
END_RECV_TABLE()
void C_EnvLight::ChangeCSMQuality()
{
switch (r_post_draw_csm_quality_mode.GetInt())
{
case 1:
{
ShadowConfig_t def[] = {
{ 154.0f, 154.0f, 0.25f, 0.0f },
{ 801.0f, 801.0f, 0.75f, 0.0f }
};
V_memcpy(shadowConfigs, def, sizeof(shadowConfigs));
}
break;
case 2:
{
ShadowConfig_t def[] = {
{ 225.0f, 225.0f, 0.25f, 0.0f },
{ 900.0f, 900.0f, 0.75f, 0.0f }
};
V_memcpy(shadowConfigs, def, sizeof(shadowConfigs));
}
break;
case 3:
{
ShadowConfig_t def[] = {
{ 350.0f, 350.0f, 0.25f, 0.0f },
{ 1000.0f, 1000.0f, 0.75f, 0.0f }
};
V_memcpy(shadowConfigs, def, sizeof(shadowConfigs));
}
break;
case 4:
{
ShadowConfig_t def[] = {
{ 400.0f, 400.0f, 0.25f, 0.0f },
{ 1250.0f, 1250.0f, 0.75f, 0.0f }
};
V_memcpy(shadowConfigs, def, sizeof(shadowConfigs));
}
break;
case 5:
{
ShadowConfig_t def[] = {
{ 64.0f, 0.0f, 0.25f, 0.0f },
{ 115.0f, 0.0f, 0.75f, 0.0f }
};
V_memcpy(shadowConfigs, def, sizeof(shadowConfigs));
}
break;
default:
{
ShadowConfig_t def[] = {
{ 154.0f, 154.0f, 0.25f, 0.0f },
{ 801.0f, 801.0f, 0.75f, 0.0f }
};
V_memcpy(shadowConfigs, def, sizeof(shadowConfigs));
}
break;
}
}
C_EnvLight::C_EnvLight()
: m_angSunAngles(vec3_angle)
, m_vecLight(vec3_origin)
, m_vecAmbient(vec3_origin)
, m_bCascadedShadowMappingEnabled(false)
{
ChangeCSMQuality();
}
C_EnvLight::~C_EnvLight()
{
if (g_pCSMEnvLight == this)
{
g_pCSMEnvLight = NULL;
}
}
void C_EnvLight::OnDataChanged(DataUpdateType_t type)
{
BaseClass::OnDataChanged(type);
if (g_pCSMEnvLight == NULL ||
/*m_bCascadedShadowMappingEnabled && */!g_pCSMEnvLight->IsCascadedShadowMappingEnabled() ||
m_vecLight.Length() > g_pCSMEnvLight->m_vecLight.Length()) // If there are multiple lights, use the brightest one if CSM is forced
{
g_pCSMEnvLight = this;
}
}
bool C_EnvLight::IsCascadedShadowMappingEnabled() const
{
const int &iCSMCvarEnabled = r_post_draw_rtt_enabled.GetInt() && m_bCascadedShadowMappingEnabled;
/*if (iCSMCvarEnabled && cvar->FindVar("r_shadows")->GetInt())
cvar->FindVar("r_shadows")->SetValue(0);
else if (!cvar->FindVar("r_shadows")->GetInt())
cvar->FindVar("r_shadows")->SetValue(1);*/
//cvar->FindVar("r_shadows")->SetValue(!iCSMCvarEnabled);
return /*m_bCascadedShadowMappingEnabled && */iCSMCvarEnabled;
}
//-----------------------------------------------------------------------------
// CPrecisionSlider
// A drop-in replacement for the slider class that contains a text entry that
// can be used to read and set the current value.
// Also provides mousewheel support.
//-----------------------------------------------------------------------------
class CPrecisionSlider : public vgui::FloatSlider
{
DECLARE_CLASS_SIMPLE(CPrecisionSlider, vgui::FloatSlider);
public:
CPrecisionSlider(Panel *parent, const char *panelName);
~CPrecisionSlider();
virtual void SetValue(float value, bool bTriggerChangeMessage = true);
virtual void OnSizeChanged(int wide, int tall);
virtual void GetTrackRect(int &x, int &y, int &w, int &h);
virtual void SetEnabled(bool state);
protected:
MESSAGE_FUNC_PARAMS(OnTextNewLine, "TextNewLine", data);
virtual void OnMouseWheeled(int delta);
private:
vgui::TextEntry *m_pTextEntry;
int m_nTextEntryWidth;
int m_nSpacing;
};
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CPrecisionSlider::CPrecisionSlider(Panel *parent, const char *panelName) : BaseClass(parent, panelName)
{
m_pTextEntry = new vgui::TextEntry(this, "PrecisionEditPanel");
m_pTextEntry->SendNewLine(true);
m_pTextEntry->SetCatchEnterKey(true);
m_pTextEntry->AddActionSignalTarget(this);
m_nTextEntryWidth = 32;
m_nSpacing = 8;
AddActionSignalTarget(parent);
}
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
CPrecisionSlider::~CPrecisionSlider()
{
}
//-----------------------------------------------------------------------------
// Override OnSizeChanged to update text entry size as well
//-----------------------------------------------------------------------------
void CPrecisionSlider::OnSizeChanged(int wide, int tall)
{
m_pTextEntry->SetBounds(wide - (m_nSpacing + m_nTextEntryWidth) + m_nSpacing, 0, m_nTextEntryWidth, tall - 12);
BaseClass::OnSizeChanged(wide, tall);
}
//-----------------------------------------------------------------------------
// Override GetTrackRect in order to adjust for the text entry
//-----------------------------------------------------------------------------
void CPrecisionSlider::GetTrackRect(int &x, int &y, int &w, int &h)
{
int wide, tall;
GetPaintSize(wide, tall);
x = 0;
y = 8;
w = wide - (_nobSize + m_nTextEntryWidth + m_nSpacing);
h = 4;
}
//-----------------------------------------------------------------------------
// Override SetValue to update the text entry data
//-----------------------------------------------------------------------------
void CPrecisionSlider::SetValue(float value, bool bTriggerChangeMessage)
{
BaseClass::SetValue(value, bTriggerChangeMessage);
char szValueString[256];
sprintf(szValueString, "%.3f", _value);
m_pTextEntry->SetText(szValueString);
}
//-----------------------------------------------------------------------------
// Override SetEnabled to also effect the text entry field
//-----------------------------------------------------------------------------
void CPrecisionSlider::SetEnabled(bool state)
{
BaseClass::SetEnabled(state);
m_pTextEntry->SetEnabled(state);
}
//-----------------------------------------------------------------------------
// Handle updates from the text entry field
//-----------------------------------------------------------------------------
void CPrecisionSlider::OnTextNewLine(KeyValues *data)
{
char buf[256];
m_pTextEntry->GetText(buf, 256);
float value;
sscanf(buf, "%f", &value);
SetValue(value);
}
//-----------------------------------------------------------------------------
// Handle mousewheel updates
//-----------------------------------------------------------------------------
void CPrecisionSlider::OnMouseWheeled(int delta)
{
BaseClass::OnMouseWheeled(delta);
if (IsEnabled())
{
float value = GetValue();
if (vgui::input()->IsKeyDown(KEY_LCONTROL) || vgui::input()->IsKeyDown(KEY_RCONTROL))
SetValue(value + delta * 4);
else
SetValue(value + delta);
}
}
class CCSMTweakPanel : vgui::Frame
{
DECLARE_CLASS_SIMPLE(CCSMTweakPanel, vgui::Frame);
public:
CCSMTweakPanel(vgui::VPANEL parent);
~CCSMTweakPanel();
void OnMessage(const KeyValues *params, vgui::VPANEL fromPanel);
private:
void LoadSettings();
struct
{
CPrecisionSlider* pOrthoSize;
CPrecisionSlider* pForwardOffset;
CPrecisionSlider* pUVOffsetX;
CPrecisionSlider* pViewDepthBiasHack;
} near, far;
};
CCSMTweakPanel::CCSMTweakPanel(vgui::VPANEL parent) : Frame(NULL, "CCSMTweakPanel")
{
SetParent(parent);
near.pOrthoSize = new CPrecisionSlider(this, "nearOrthoSize");
near.pOrthoSize->SetRange(0, 4096);
near.pForwardOffset = new CPrecisionSlider(this, "nearForwardOffset");
near.pForwardOffset->SetRange(0, 4096);
near.pUVOffsetX = new CPrecisionSlider(this, "nearForwardOffsetX");
near.pUVOffsetX->SetRange(0, 4096);
near.pViewDepthBiasHack = new CPrecisionSlider(this, "nearDepthBiasHack");
near.pViewDepthBiasHack->SetRange(0, 4096);
far.pOrthoSize = new CPrecisionSlider(this, "farOrthoSize");
far.pOrthoSize->SetRange(0, 4096);
far.pForwardOffset = new CPrecisionSlider(this, "farForwardOffset");
far.pForwardOffset->SetRange(0, 4096);
far.pUVOffsetX = new CPrecisionSlider(this, "farForwardOffsetX");
far.pUVOffsetX->SetRange(0, 4096);
far.pViewDepthBiasHack = new CPrecisionSlider(this, "farDepthBiasHack");
far.pViewDepthBiasHack->SetRange(0, 4096);
SetSize(128, 256);
LoadControlSettings("Resource\\CSMTweakPanel.res");
SetDeleteSelfOnClose(true);
SetTitle("CSM tweaks", true);
SetVisible(true);
MoveToFront();
SetZPos(1500);
SetMouseInputEnabled(true);
SetCursorAlwaysVisible(true);
LoadSettings();
}
CCSMTweakPanel::~CCSMTweakPanel()
{
SetCursorAlwaysVisible(false);
}
void CCSMTweakPanel::OnMessage(const KeyValues *params, vgui::VPANEL fromPanel)
{
BaseClass::OnMessage(params, fromPanel);
if (!g_pCSMEnvLight)
return;
if (!Q_stricmp("SliderMoved", params->GetName()))
{
Panel* panel = reinterpret_cast< Panel* >(const_cast< KeyValues* >(params)->GetPtr("panel", NULL));
if (panel == near.pOrthoSize)
{
g_pCSMEnvLight->shadowConfigs[0].flOrthoSize = near.pOrthoSize->GetValue();
}
else if (panel == near.pForwardOffset)
{
g_pCSMEnvLight->shadowConfigs[0].flForwardOffset = near.pForwardOffset->GetValue();
}
else if (panel == near.pUVOffsetX)
{
g_pCSMEnvLight->shadowConfigs[0].flUVOffsetX = near.pUVOffsetX->GetValue();
}
else if (panel == near.pViewDepthBiasHack)
{
g_pCSMEnvLight->shadowConfigs[0].flViewDepthBiasHack = near.pViewDepthBiasHack->GetValue();
}
else if (panel == far.pOrthoSize)
{
g_pCSMEnvLight->shadowConfigs[1].flOrthoSize = far.pOrthoSize->GetValue();
}
else if (panel == far.pForwardOffset)
{
g_pCSMEnvLight->shadowConfigs[1].flForwardOffset = far.pForwardOffset->GetValue();
}
else if (panel == far.pUVOffsetX)
{
g_pCSMEnvLight->shadowConfigs[1].flUVOffsetX = far.pUVOffsetX->GetValue();
}
else if (panel == far.pViewDepthBiasHack)
{
g_pCSMEnvLight->shadowConfigs[1].flViewDepthBiasHack = far.pViewDepthBiasHack->GetValue();
}
}
}
void CCSMTweakPanel::LoadSettings()
{
if (g_pCSMEnvLight)
{
const auto& data = g_pCSMEnvLight->shadowConfigs;
near.pForwardOffset->SetValue(data[0].flForwardOffset, false);
near.pOrthoSize->SetValue(data[0].flOrthoSize, false);
near.pUVOffsetX->SetValue(data[0].flUVOffsetX, false);
near.pViewDepthBiasHack->SetValue(data[0].flViewDepthBiasHack, false);
far.pForwardOffset->SetValue(data[1].flForwardOffset, false);
far.pOrthoSize->SetValue(data[1].flOrthoSize, false);
far.pUVOffsetX->SetValue(data[1].flUVOffsetX, false);
far.pViewDepthBiasHack->SetValue(data[1].flViewDepthBiasHack, false);
}
}
CON_COMMAND(csm_tweak, "")
{
if (g_pCSMEnvLight)
{
new CCSMTweakPanel(enginevgui->GetPanel(PANEL_CLIENTDLL));
}
}