Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 101 additions & 1 deletion Core/GameEngineDevice/Source/W3DDevice/GameClient/BaseHeightMap.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
Expand Down Expand Up @@ -492,6 +492,13 @@ void BaseHeightMapRenderObjClass::ReAcquireResources(void)
}
}

// --------
static float invLerp(float a, float b, float v)
{
if (a == b) return 0.0f; // avoid divide by zero
return (v - a) / (b - a);
}

//=============================================================================
// BaseHeightMapRenderObjClass::doTheLight
//=============================================================================
Expand Down Expand Up @@ -591,6 +598,99 @@ void BaseHeightMapRenderObjClass::doTheLight(VERTEX_FORMAT *vb, Vector3*light, V
if (shadeB > 1.0) shadeB = 1.0;
if(shadeB < 0.0f) shadeB = 0.0f;

// ---------------------------------------------
// Height based ambient light factor (for water)
// ---------------------------------------------
if (TheGlobalData &&
TheGlobalData->m_terrainHeightAmbientLightHeightStart > 0 &&
(TheGlobalData->m_terrainHeightAmbientLightHeight1 >= 0 || TheGlobalData->m_terrainHeightAmbientLightHeight2 >= 0) &&
vb->z <= TheGlobalData->m_terrainHeightAmbientLightHeightStart
) {
Real col1R, col1G, col1B, col2R, col2G, col2B;
//Real factor1 = 0.0;
//Real factor2 = 0.0;
Real height1 = -1;
Real height2 = -1;

Real colR;
Real colG;
Real colB;

// case 1: only one color
if (TheGlobalData->m_terrainHeightAmbientLightHeight1 <= 0)
{
col1R = TheGlobalData->m_terrainHeightAmbientLightColor2.red;
col1G = TheGlobalData->m_terrainHeightAmbientLightColor2.green;
col1B = TheGlobalData->m_terrainHeightAmbientLightColor2.blue;
height1 = TheGlobalData->m_terrainHeightAmbientLightHeight2;
}
else if (TheGlobalData->m_terrainHeightAmbientLightHeight2 <= 0) {
col1R = TheGlobalData->m_terrainHeightAmbientLightColor1.red;
col1G = TheGlobalData->m_terrainHeightAmbientLightColor1.green;
col1B = TheGlobalData->m_terrainHeightAmbientLightColor1.blue;
height1 = TheGlobalData->m_terrainHeightAmbientLightHeight1;
}
else
{ // case 2: both colors

col1R = TheGlobalData->m_terrainHeightAmbientLightColor1.red;
col1G = TheGlobalData->m_terrainHeightAmbientLightColor1.green;
col1B = TheGlobalData->m_terrainHeightAmbientLightColor1.blue;
col2R = TheGlobalData->m_terrainHeightAmbientLightColor2.red;
col2G = TheGlobalData->m_terrainHeightAmbientLightColor2.green;
col2B = TheGlobalData->m_terrainHeightAmbientLightColor2.blue;
height1 = TheGlobalData->m_terrainHeightAmbientLightHeight1;
height2 = TheGlobalData->m_terrainHeightAmbientLightHeight2;
}

bool multiply = !TheGlobalData->m_terrainHeightAmbientLightAdditive;
Real base;
if (multiply)
base = 1.0;
else
base = 0.0;

if (vb->z > height1) {
Real t = WWMath::Clamp(invLerp(TheGlobalData->m_terrainHeightAmbientLightHeightStart, height1, vb->z));
colR = col1R * t + (1.0 - t) * base;
colG = col1G * t + (1.0 - t) * base;
colB = col1B * t + (1.0 - t) * base;
}

// Between height1 and height2
else if (height2 > -1 && vb->z > height2)
{
Real t = WWMath::Clamp(invLerp(height1, height2, vb->z));
Real factor1 = 1.0f - t; // 1 → 0
Real factor2 = t; // 0 → 1

colR = col1R * factor1 + col2R * factor2;
colG = col1G * factor1 + col2G * factor2;
colB = col1B * factor1 + col2B * factor2;
}
// below
else {
colR = col2R;
colG = col2G;
colB = col2B;
}

if (multiply) {
shadeR *= colR;
shadeG *= colG;
shadeB *= colB;
}
else {
shadeR = WWMath::Clamp(shadeR + colR);
shadeG = WWMath::Clamp(shadeG + colG);
shadeB = WWMath::Clamp(shadeB + colB);
}
}
// ---------------------------------------------



// Old, inactive code
if (m_useDepthFade && vb->z <= TheGlobalData->m_waterPositionZ)
{ //height is below water level
//reduce lighting values based on light fall off as it travels through water.
Expand Down
8 changes: 8 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/Common/GlobalData.h
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,14 @@ class GlobalData : public SubsystemInterface
Bool m_heightAboveTerrainIncludesWater;
Bool m_hideScorchmarksAboveGround;

// Water depth lighting
RGBColor m_terrainHeightAmbientLightColor1;
RGBColor m_terrainHeightAmbientLightColor2;
Real m_terrainHeightAmbientLightHeightStart;
Real m_terrainHeightAmbientLightHeight1;
Real m_terrainHeightAmbientLightHeight2;
Bool m_terrainHeightAmbientLightAdditive;

// the trailing '\' is included!
const AsciiString &getPath_UserData() const { return m_userDataDir; }

Expand Down
22 changes: 22 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,14 @@ GlobalData* GlobalData::m_theOriginal = NULL;
{"DefaultExcludedDeathTypes", INI::parseDeathTypeFlagsList, NULL, offsetof(GlobalData, m_defaultExcludedDeathTypes) },
{"HeightAboveTerrainIncludesWater", INI::parseBool, NULL, offsetof(GlobalData, m_heightAboveTerrainIncludesWater) },
{"HideScorchmarksAboveGround", INI::parseBool, NULL, offsetof(GlobalData, m_hideScorchmarksAboveGround) },


{ "TerrainHeightAmbientLightColor1", INI::parseRGBColor, NULL, offsetof(GlobalData, m_terrainHeightAmbientLightColor1) },
{ "TerrainHeightAmbientLightColor2", INI::parseRGBColor, NULL, offsetof(GlobalData, m_terrainHeightAmbientLightColor2) },
{ "TerrainHeightAmbientLightStart", INI::parseReal, NULL, offsetof(GlobalData, m_terrainHeightAmbientLightHeightStart) },
{ "TerrainHeightAmbientLightHeight1", INI::parseReal, NULL, offsetof(GlobalData, m_terrainHeightAmbientLightHeight1) },
{ "TerrainHeightAmbientLightHeight2", INI::parseReal, NULL, offsetof(GlobalData, m_terrainHeightAmbientLightHeight2) },
{ "TerrainHeightAmbientLightAdditive", INI::parseBool, NULL, offsetof(GlobalData, m_terrainHeightAmbientLightAdditive) },
{ NULL, NULL, NULL, 0 } // keep this last

};
Expand Down Expand Up @@ -1163,6 +1171,20 @@ GlobalData::GlobalData()

m_heightAboveTerrainIncludesWater = false;

m_terrainHeightAmbientLightColor1.red = 0;
m_terrainHeightAmbientLightColor1.green = 0;
m_terrainHeightAmbientLightColor1.blue = 0;

m_terrainHeightAmbientLightColor2.red = 0;
m_terrainHeightAmbientLightColor2.green = 0;
m_terrainHeightAmbientLightColor2.blue = 0;

m_terrainHeightAmbientLightHeightStart = -1;
m_terrainHeightAmbientLightHeight1 = -1;
m_terrainHeightAmbientLightHeight2 = -1;

m_terrainHeightAmbientLightAdditive = false;

} // end GlobalData


Expand Down